Skip to content

Commit

Permalink
Use custom allocator for aligned memory
Browse files Browse the repository at this point in the history
  • Loading branch information
williamyang98 committed Feb 25, 2024
1 parent 51125f7 commit 0216d49
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 129 deletions.
10 changes: 5 additions & 5 deletions src/ofdm/ofdm_demodulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
#include "./circular_buffer.h"
#include "utility/observable.h"
#include "utility/span.h"
#include "utility/joint_allocate.h"
#include "utility/aligned_allocator.hpp"
#include "viterbi_config.h"

typedef struct fftwf_plan_s* fftwf_plan; \
struct fftwf_plan_s;

class OFDM_Demod_Pipeline;
class OFDM_Demod_Coordinator;
Expand Down Expand Up @@ -72,8 +72,8 @@ class OFDM_Demod
bool m_is_null_end_found;
float m_signal_l1_average;
// fft
fftwf_plan m_fft_plan;
fftwf_plan m_ifft_plan;
fftwf_plan_s* m_fft_plan;
fftwf_plan_s* m_ifft_plan;
// threads
std::unique_ptr<OFDM_Demod_Coordinator> m_coordinator;
std::vector<std::unique_ptr<OFDM_Demod_Pipeline>> m_pipelines;
Expand All @@ -82,7 +82,7 @@ class OFDM_Demod
// callback for when ofdm is completed
Observable<tcb::span<const viterbi_bit_t>> m_obs_on_ofdm_frame;
// Joint memory allocation block
AlignedVector<uint8_t> m_joint_data_block;
std::vector<uint8_t, AlignedAllocator<uint8_t>> m_joint_data_block;
// 1. pipeline reader double buffer
OFDM_Frame_Buffer<std::complex<float>> m_active_buffer;
OFDM_Frame_Buffer<std::complex<float>> m_inactive_buffer;
Expand Down
49 changes: 49 additions & 0 deletions src/utility/aligned_allocator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include <assert.h>
#include <cstddef>
#include <new>
#include <type_traits>

// C++17 aligned allocator
// Sources: https://en.cppreference.com/w/cpp/named_req/Allocator
// https://en.cppreference.com/w/cpp/memory/allocator_traits
// https://en.cppreference.com/w/cpp/memory/new/operator_new
template <typename T>
class AlignedAllocator
{
public:
using value_type = T;
using is_always_equal = std::false_type;
using propagate_on_container_copy_assignment = std::false_type; // do not copy allocator when copying object
using propagate_on_container_move_assignment = std::true_type; // move allocator when moving object
using propagate_on_container_swap = std::true_type;
template <typename U>
struct rebind {
using other = AlignedAllocator<U>;
};
static constexpr size_t default_alignment = sizeof(std::size_t);
private:
std::size_t m_alignment;
public:
explicit AlignedAllocator(std::size_t alignment=default_alignment): m_alignment(alignment) {}
[[nodiscard]] T* allocate(std::size_t length) {
return reinterpret_cast<T*>(operator new(length*sizeof(T), std::align_val_t(m_alignment)));
}
void deallocate(T* const ptr, std::size_t /*length*/) const {
assert(reinterpret_cast<uintptr_t>(ptr) % m_alignment == 0);
operator delete(ptr, std::align_val_t(m_alignment));
}
bool operator==(const AlignedAllocator& other) const noexcept {
return m_alignment == other.m_alignment;
}
bool operator!=(const AlignedAllocator& other) const noexcept {
return m_alignment != other.m_alignment;
}
// cast between types
inline size_t get_alignment() const { return m_alignment; }
template <typename U>
explicit AlignedAllocator(const AlignedAllocator<U>& other): m_alignment(other.get_alignment()) {}
template <typename U>
operator AlignedAllocator<U>() const { return AlignedAllocator<U>(m_alignment); }
};
118 changes: 0 additions & 118 deletions src/utility/aligned_vector.h

This file was deleted.

13 changes: 7 additions & 6 deletions src/utility/joint_allocate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
#include <stdint.h>
#include <new>
#include <assert.h>
#include "span.h"
#include "aligned_vector.h"
#include <vector>
#include "./span.h"
#include "./aligned_allocator.hpp"

// Define the specification for each buffer inside the joint block
struct BufferParameters {
Expand All @@ -15,12 +16,12 @@ struct BufferParameters {
: length(_length), alignment(_alignment) {}
};

static AlignedVector<uint8_t> AllocateJoint(size_t curr_size, size_t align_size) {
return AlignedVector<uint8_t>(curr_size, align_size);
static std::vector<uint8_t, AlignedAllocator<uint8_t>> AllocateJoint(size_t curr_size, size_t align_size) {
return std::vector<uint8_t, AlignedAllocator<uint8_t>>(curr_size, AlignedAllocator<uint8_t>(align_size));
}

template <typename T, typename ... Ts>
static AlignedVector<uint8_t> AllocateJoint(size_t curr_joint_size, size_t joint_alignment, tcb::span<T>& buf, BufferParameters params, Ts&& ... args) {
static std::vector<uint8_t, AlignedAllocator<uint8_t>> AllocateJoint(size_t curr_joint_size, size_t joint_alignment, tcb::span<T>& buf, BufferParameters params, Ts&& ... args) {
// create padding so that next buffer has its alignment
const auto align_elem_size = params.alignment ? params.alignment : sizeof(T);
const size_t padded_joint_size = ((curr_joint_size+align_elem_size-1) / align_elem_size) * align_elem_size;
Expand All @@ -46,6 +47,6 @@ static AlignedVector<uint8_t> AllocateJoint(size_t curr_joint_size, size_t joint

// Recursive template for creating a jointly allocated block
template <typename T, typename ... Ts>
static AlignedVector<uint8_t> AllocateJoint(tcb::span<T>& buf, BufferParameters params, Ts&& ... args) {
static std::vector<uint8_t, AlignedAllocator<uint8_t>> AllocateJoint(tcb::span<T>& buf, BufferParameters params, Ts&& ... args) {
return AllocateJoint(0, 1, buf, params, args...);
}

0 comments on commit 0216d49

Please sign in to comment.