Skip to content

Commit

Permalink
use the new allocator for aligned allocations
Browse files Browse the repository at this point in the history
The new implementation is more C++-like (can be used with STL container)
and more robust (overflow handling, strict aliasing rule, …).

Refs: scality#222
  • Loading branch information
slaperche-scality committed Oct 17, 2018
1 parent 12bccc2 commit 35ad3a8
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 58 deletions.
12 changes: 6 additions & 6 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,19 @@ Benchmark<T>::~Benchmark()

if (d_chunks != nullptr) {
for (int i = 0; i < k; i++) {
quadiron::aligned_deallocate<uint8_t>(d_chunks->at(i));
this->allocator.deallocate(d_chunks->at(i), chunk_size);
}
delete d_chunks;
}
if (c_chunks != nullptr) {
for (int i = 0; i < n_c; i++) {
quadiron::aligned_deallocate<uint8_t>(c_chunks->at(i));
this->allocator.deallocate(c_chunks->at(i), chunk_size);
}
delete c_chunks;
}
if (r_chunks != nullptr) {
for (int i = 0; i < k; i++) {
quadiron::aligned_deallocate<uint8_t>(r_chunks->at(i));
this->allocator.deallocate(r_chunks->at(i), chunk_size);
}
delete r_chunks;
}
Expand Down Expand Up @@ -199,13 +199,13 @@ int Benchmark<T>::init()
r_chunks = new std::vector<uint8_t*>(k);

for (i = 0; i < k; i++) {
d_chunks->at(i) = quadiron::aligned_allocate<uint8_t>(chunk_size);
d_chunks->at(i) = this->allocator.allocate(chunk_size);
}
for (i = 0; i < n_c; i++) {
c_chunks->at(i) = quadiron::aligned_allocate<uint8_t>(chunk_size);
c_chunks->at(i) = this->allocator.allocate(chunk_size);
}
for (i = 0; i < k; i++) {
r_chunks->at(i) = quadiron::aligned_allocate<uint8_t>(chunk_size);
r_chunks->at(i) = this->allocator.allocate(chunk_size);
}

// Allocate memory for iostreambufs
Expand Down
2 changes: 2 additions & 0 deletions benchmark/benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <sys/types.h>

#include "quadiron.h"
#include "simd/simd.h"

#include "core.h"
#include "iostreambuf.h"
Expand Down Expand Up @@ -298,6 +299,7 @@ class Benchmark {
PRNG* prng = nullptr;
quadiron::fec::FecCode<T>* fec = nullptr;
Params_t* params = nullptr;
quadiron::simd::AlignedAllocator<uint8_t> allocator;

bool systematic_ec = false;

Expand Down
39 changes: 0 additions & 39 deletions src/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,45 +105,6 @@ static inline std::mt19937& prng()
return PRNG;
}

template <typename T>
inline T* aligned_allocate(size_t size)
{
#ifdef QUADIRON_USE_SIMD
size_t len = simd::ALIGNMENT + size * sizeof(T);
uint8_t* ptr = new uint8_t[len];
if (!ptr)
return nullptr;
unsigned offset = (unsigned)((uintptr_t)ptr % simd::ALIGNMENT);
ptr += simd::ALIGNMENT - offset - 1;
// store offset
ptr[0] = (uint8_t)offset; // NOLINT
// increment ptr to the aligned location
ptr++;
T* data = reinterpret_cast<T*>(ptr);
return data;
#else
T* data = new T[size];
if (!data)
return nullptr;
return data;
#endif
}

template <typename T>
inline void aligned_deallocate(T* data)
{
if (!data)
return;
#ifdef QUADIRON_USE_SIMD
uint8_t* ptr = (uint8_t*)data;
unsigned offset = *(ptr - 1);
ptr -= simd::ALIGNMENT - offset;
delete[] ptr;
#else
delete[] data;
#endif
}

} // namespace quadiron

#endif
16 changes: 9 additions & 7 deletions src/vec_buffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <vector>

#include "core.h"
#include "simd/simd.h"

namespace quadiron {
namespace vec {
Expand Down Expand Up @@ -131,6 +132,7 @@ class Buffers final {
int n;

private:
simd::AlignedAllocator<T> allocator;
BufMemAlloc mem_alloc_case = BufMemAlloc::FULL;
T* zeros = nullptr;
};
Expand All @@ -151,7 +153,7 @@ Buffers<T>::Buffers(int n, size_t size)
this->mem_alloc_case = BufMemAlloc::FULL;
mem.reserve(n);
for (int i = 0; i < n; i++) {
mem.push_back(aligned_allocate<T>(size));
mem.push_back(this->allocator.allocate(size));
}
}

Expand Down Expand Up @@ -193,7 +195,7 @@ Buffers<T>::Buffers(const Buffers<T>& vec, int n)

mem.reserve(n);
for (i = 0; i < this->n; i++) {
mem.push_back(aligned_allocate<T>(this->size));
mem.push_back(this->allocator.allocate(size));
}

int copy_len = (this->n <= vec_n) ? this->n : vec_n;
Expand Down Expand Up @@ -238,7 +240,7 @@ Buffers<T>::Buffers(const Buffers<T>& vec, int begin, int end)
} else { // slice and padding zeros
this->mem_alloc_case = BufMemAlloc::ZERO_EXTEND;

this->zeros = aligned_allocate<T>(this->size);
this->zeros = this->allocator.allocate(size);
std::memset(this->zeros, 0, this->size * sizeof(T));

mem.insert(mem.end(), vec_mem.begin() + begin, vec_mem.end());
Expand Down Expand Up @@ -312,7 +314,7 @@ Buffers<T>::Buffers(
} else { // output is zero-extended & shuffled from `vec`
this->mem_alloc_case = BufMemAlloc::ZERO_EXTEND;

this->zeros = aligned_allocate<T>(this->size);
this->zeros = this->allocator.allocate(size);
std::memset(this->zeros, 0, this->size * sizeof(T));

for (unsigned i = 0; i < n; ++i) {
Expand All @@ -330,10 +332,10 @@ Buffers<T>::~Buffers()
if (this->mem_alloc_case != BufMemAlloc::NONE && mem.size() > 0) {
if (this->mem_alloc_case == BufMemAlloc::FULL) {
for (int i = 0; i < n; i++) {
aligned_deallocate<T>(mem[i]);
this->allocator.deallocate(mem[i], size);
}
} else if (this->mem_alloc_case == BufMemAlloc::ZERO_EXTEND) {
aligned_deallocate<T>(this->zeros);
this->allocator.deallocate(this->zeros, size);
}
}
}
Expand Down Expand Up @@ -375,7 +377,7 @@ inline void Buffers<T>::set(int i, T* buf)
assert(i >= 0 && i < n);

if ((mem_alloc_case == BufMemAlloc::NONE) && (mem[i] != nullptr))
aligned_deallocate<T>(mem[i]);
this->allocator.deallocate(mem[i], size);

mem[i] = buf;
}
Expand Down
14 changes: 9 additions & 5 deletions src/vec_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "core.h"
#include "gf_ring.h"
#include "simd/simd.h"
#include "vec_cast.h"
#include "vec_doubled.h"

Expand Down Expand Up @@ -108,6 +109,7 @@ class Vector {
T* mem;
int mem_len;
bool new_mem;
simd::AlignedAllocator<T> allocator;
};

template <typename T>
Expand All @@ -116,7 +118,7 @@ Vector<T>::Vector(const gf::RingModN<T>& rn, int n, T* mem, int mem_len)
this->rn = &rn;
this->n = n;
if (mem == nullptr) {
this->mem = aligned_allocate<T>(n);
this->mem = this->allocator.allocate(n);
this->mem_len = n;
this->new_mem = true;
} else {
Expand All @@ -139,8 +141,9 @@ Vector<T>::Vector(const gf::RingModN<T>& rn, std::initializer_list<T> values)
template <typename T>
Vector<T>::~Vector()
{
if (new_mem)
aligned_deallocate<T>(this->mem);
if (new_mem) {
this->allocator.deallocate(this->mem, n);
}
}

template <typename T>
Expand Down Expand Up @@ -203,8 +206,9 @@ inline T* Vector<T>::get_mem() const
template <typename T>
inline void Vector<T>::set_mem(T* mem, int mem_len)
{
if (new_mem)
aligned_deallocate<T>(this->mem);
if (new_mem) {
this->allocator.deallocate(this->mem, n);
}
new_mem = false;
this->mem = mem;
this->mem_len = mem_len;
Expand Down
5 changes: 4 additions & 1 deletion test/buffers_utest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
#include <gtest/gtest.h>

#include "quadiron.h"
#include "simd/simd.h"

namespace vec = quadiron::vec;
namespace gf = quadiron::gf;

template <typename T>
class BuffersTest : public ::testing::Test {
public:
quadiron::simd::AlignedAllocator<T> allocator;

std::unique_ptr<vec::Buffers<T>>
gen_buffers_rand_data(int n, int size, int _max = 0)
{
Expand All @@ -49,7 +52,7 @@ class BuffersTest : public ::testing::Test {
auto vec = std::make_unique<vec::Buffers<T>>(n, size);

for (int i = 0; i < n; i++) {
T* buf = quadiron::aligned_allocate<T>(size);
T* buf = this->allocator.allocate(size);
for (int j = 0; j < size; j++) {
buf[j] = dis(prng);
}
Expand Down

0 comments on commit 35ad3a8

Please sign in to comment.