Skip to content

Commit

Permalink
Buffers: re-arrange & add new functions
Browse files Browse the repository at this point in the history
- Move functions to public: `compute_meta_size()`, `compute_size()`
- Add `get_meta(buf_id, ele_id)` getting meta of a given element
- Add `get(buf_id, ele_id, lo, hi)` retrieving an unpacked value
corresponding an element & its meta
  • Loading branch information
lamphamsy committed Apr 25, 2019
1 parent 5a6693d commit 1d82832
Showing 1 changed file with 143 additions and 47 deletions.
190 changes: 143 additions & 47 deletions src/vec_buffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ enum class BufMemAlloc {
/** A vector of `n` DATA buffers (array of T) and an OPTINAL vector of `n` META
* buffers (array of T). A meta buffer corresponds to a data buffer. Every
*`s`-byte data element of a data buffer corresponds to a `s`-bit element of the
* meta buffer.
* meta buffer, where `s = sizeof(T)`.`
* A pair of data and meta elements can represent an integer of `8*s + s`-bits
*
* Each data element points to a buffer of size `m * sizeof(T)` bytes.
* Hence, each meta element points to a buffer of size
* `bsize = m * sizeof(T) / 8` bytes that should be an integer, i.e.
Expand Down Expand Up @@ -141,8 +143,10 @@ class Buffers final {
void set(int i, T* buf);
T* get(int i);
const T* get(int i) const;
void get(int buf_id, size_t ele_id, T& hi, T& lo) const;
uint8_t* get_meta(int i);
const uint8_t* get_meta(int i) const;
T get_meta(int buf_id, size_t ele_id) const;
const std::vector<T*>& get_mem() const;
const std::vector<uint8_t*>& get_meta() const;
void set_mem(std::vector<T*>* mem);
Expand All @@ -154,10 +158,47 @@ class Buffers final {
unsigned data_len,
unsigned group_len);
void radix2_fft_inv_prepare(const Buffers<T>& input);
void reset_meta();
friend bool operator==<T>(const Buffers<T>& lhs, const Buffers<T>& rhs);
void dump(void);
void swap(unsigned i, unsigned j);

/** Calculate meta size given a buffer size
* meta size := ceil(size * sizeof(T) / CHAR_BIT)
*
* @param s - given size, in words
* @return meta size, in bytes
*/
static size_t compute_meta_size(size_t s)
{
assert(s > 0);

const size_t bytes = s * sizeof(T);
size_t r = bytes / CHAR_BIT;
while (r * CHAR_BIT < bytes) {
r++;
}
return r;
};

/** Calculate buffer size given a meta_size
* buffer size := ceil(meta_size * CHAR_BIT / sizeof(T))
*
* @param m_size - given meta size, in bytes
* @return meta size
*/
static size_t compute_size(size_t m_size)
{
assert(m_size > 0);

const size_t bytes = m_size * CHAR_BIT;
size_t r = bytes / sizeof(T);
while (r * sizeof(T) < bytes) {
r++;
}
return r;
};

/** Calculate conventional size of buffers
* Conentional size is the lowest number of words that is at least a given
* `s` and satisfy the following conditions:
Expand Down Expand Up @@ -216,43 +257,12 @@ class Buffers final {
uint8_t* zeros_meta = nullptr;
bool m_meta = false;

/** Calculate meta size given a buffer size
* meta size := ceil(size * sizeof(T) / CHAR_BIT)
*
* @param s - given size, in words
* @return meta size, in bytes
*/
static size_t compute_meta_size(size_t s)
{
assert(s > 0);
unsigned meta_bits_nb = 0;
T threshold = 0;
T half_element_mask;
T half_meta_mask;

const size_t bytes = s * sizeof(T);
size_t r = bytes / CHAR_BIT;
while (r * CHAR_BIT < bytes) {
r++;
}
return r;
};

/** Calculate buffer size given a meta_size
* buffer size := ceil(meta_size * CHAR_BIT / sizeof(T))
*
* @param m_size - given meta size, in bytes
* @return meta size
*/
static size_t compute_size(size_t m_size)
{
assert(m_size > 0);

const size_t bytes = m_size * CHAR_BIT;
size_t r = bytes / sizeof(T);
while (r * sizeof(T) < bytes) {
r++;
}
return r;
};

void compute_meta_size();
void init_meta();
void allocate_meta(bool init_zero = false);
};

Expand All @@ -277,7 +287,7 @@ Buffers<T>::Buffers(int n, size_t size, bool has_meta)

if (has_meta) {
this->m_meta = has_meta;
this->compute_meta_size();
this->init_meta();
this->allocate_meta(true);
}
}
Expand All @@ -304,7 +314,7 @@ Buffers<T>::Buffers(

if (meta) {
this->m_meta = true;
this->compute_meta_size();
this->init_meta();
this->meta = *meta;
}
}
Expand Down Expand Up @@ -346,7 +356,7 @@ Buffers<T>::Buffers(const Buffers<T>& vec, int n)

this->m_meta = vec.has_meta();
if (this->m_meta) {
this->compute_meta_size();
this->init_meta();
this->allocate_meta();

for (i = 0; i < copy_len; i++) {
Expand Down Expand Up @@ -401,7 +411,7 @@ Buffers<T>::Buffers(const Buffers<T>& vec, int begin, int end)
this->m_meta = vec.has_meta();
if (this->m_meta) {
const std::vector<uint8_t*> vec_meta = vec.get_meta();
this->compute_meta_size();
this->init_meta();
meta.reserve(this->n);
// slice from input buffers
if (end <= vec.get_n()) {
Expand Down Expand Up @@ -441,7 +451,7 @@ Buffers<T>::Buffers(const Buffers<T>& vec1, const Buffers<T>& vec2)

this->m_meta = vec1.has_meta();
if (this->m_meta) {
this->compute_meta_size();
this->init_meta();
meta.reserve(this->n);
meta.insert(meta.end(), vec1.get_meta().begin(), vec1.get_meta().end());
meta.insert(meta.end(), vec2.get_meta().begin(), vec2.get_meta().end());
Expand Down Expand Up @@ -502,7 +512,7 @@ Buffers<T>::Buffers(

this->m_meta = vec.has_meta();
if (this->m_meta) {
this->compute_meta_size();
this->init_meta();

const std::vector<uint8_t*> vec_meta = vec.get_meta();
// output is sliced & shuffled from `vec`
Expand Down Expand Up @@ -544,9 +554,17 @@ Buffers<T>::~Buffers()
}

template <typename T>
inline void Buffers<T>::compute_meta_size()
inline void Buffers<T>::init_meta()
{
meta_size = Buffers<T>::compute_meta_size(size);
meta_bits_nb = sizeof(T);
threshold = (static_cast<T>(1) << meta_bits_nb) - 1;

half_element_mask = (static_cast<T>(1) << (CHAR_BIT * sizeof(T) / 2)) - 1;
half_meta_mask = (static_cast<T>(1) << (meta_bits_nb / 2)) - 1;
if (half_meta_mask == 0) {
half_meta_mask = 1;
}
}

template <typename T>
Expand All @@ -558,9 +576,7 @@ inline void Buffers<T>::allocate_meta(bool init_zero)
}

if (init_zero) {
for (int i = 0; i < n; i++) {
std::fill_n(meta[i], meta_size, 0);
}
reset_meta();
}
}

Expand Down Expand Up @@ -632,6 +648,34 @@ inline const T* Buffers<T>::get(int i) const
return mem[i];
}

/** Get unpacked `j`th element at the `i`th buffer
* Return two integers `lo` (`hi`) whose
* - low half part is the low (or high) part of the `j`th element
* - high half part is the low (or high) part of the meta of the `j`th element
*
* @param buf_id - index of buffer
* @param ele_id - index of element in the ith buffer
* @param hi - high half part of the unpacked element
* @param lo - low half part of the unpacked element
*/
template <typename T>
inline void Buffers<T>::get(int buf_id, size_t ele_id, T& hi, T& lo) const
{
assert(buf_id >= 0 && buf_id < n);
assert(ele_id >= 0 && ele_id < size);

T m_value = get_meta(buf_id, ele_id);
T value = mem[buf_id][ele_id];
const T half = CHAR_BIT * sizeof(T) / 2;

lo = (value & half_element_mask) | ((m_value & half_meta_mask) << half);

value = static_cast<T>(value) >> half;
m_value = static_cast<T>(m_value) >> (meta_bits_nb / 2);

hi = (value & half_element_mask) | ((m_value & half_meta_mask) << half);
}

template <typename T>
inline uint8_t* Buffers<T>::get_meta(int i)
{
Expand All @@ -658,6 +702,47 @@ inline const std::vector<uint8_t*>& Buffers<T>::get_meta() const
return meta;
}

/** Get meta value of the `j`th element at the `i`th buffer
*
* @param buf_id - index of buffer
* @param ele_id - index of element in the ith buffer
* @return meta value
*/
template <typename T>
inline T Buffers<T>::get_meta(int buf_id, size_t ele_id) const
{
assert(buf_id >= 0 && buf_id < n);
assert(ele_id >= 0 && ele_id < size);

const uint8_t* meta_arr = meta[buf_id];

const size_t bits_nb = ele_id * meta_bits_nb;
// begin meta
const size_t begin_id = bits_nb / CHAR_BIT;
// end meta, inclusively
const size_t end_id = (bits_nb + meta_bits_nb - 1) / CHAR_BIT;
// bit offset at the first meta
const size_t begin_offset = bits_nb % CHAR_BIT;

// get from the 1st meta
T val = threshold & (static_cast<T>(meta_arr[begin_id]) >> begin_offset);

// get from next metas, before the last one
for (size_t i = 1; i < end_id - begin_id; ++i) {
const size_t j = i + begin_id;
val |= static_cast<T>(meta_arr[j])
<< (CHAR_BIT - begin_offset + i * CHAR_BIT);
}
// get from the last meta
if (end_id > begin_id) {
const size_t end_offset = (begin_offset + meta_bits_nb) % CHAR_BIT;
const T mask_end = (static_cast<T>(1) << (end_offset + 1)) - 1;
val |= mask_end & meta_arr[end_id];
}

return val;
}

template <typename T>
inline void Buffers<T>::set_mem(std::vector<T*>* mem)
{
Expand Down Expand Up @@ -801,6 +886,17 @@ inline void Buffers<T>::radix2_fft_inv_prepare(const Buffers<T>& input)
}
}

/// Reset meta buffers
template <typename T>
inline void Buffers<T>::reset_meta()
{
if (m_meta) {
for (int i = 0; i < n; i++) {
std::fill_n(meta[i], meta_size, 0);
}
}
}

template <typename T>
void Buffers<T>::dump(void)
{
Expand Down

0 comments on commit 1d82832

Please sign in to comment.