Use static alignment for DataLayout

This commit is contained in:
Patrick Niklaus 2018-03-15 11:13:13 +00:00
parent f7b7335d75
commit 653f647fee
2 changed files with 40 additions and 40 deletions

View File

@ -16,14 +16,12 @@ struct Block
{
std::uint64_t num_entries;
std::uint64_t byte_size;
std::uint64_t entry_size;
std::uint64_t entry_align;
};
template <typename T> Block make_block(uint64_t num_entries)
{
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
return Block{num_entries, sizeof(T) * num_entries, sizeof(T), alignof(T)};
return Block{num_entries, sizeof(T) * num_entries};
}
}
}

View File

@ -94,8 +94,9 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"MANEUVER_OVERRIDES",
"MANEUVER_OVERRIDE_NODE_SEQUENCES"};
struct DataLayout
class DataLayout
{
public:
enum BlockID
{
NAME_CHAR_DATA = 0,
@ -174,8 +175,6 @@ struct DataLayout
NUM_BLOCKS
};
std::array<Block, NUM_BLOCKS> blocks;
DataLayout() : blocks{} {}
inline void SetBlock(BlockID bid, Block block) { blocks[bid] = std::move(block); }
@ -189,47 +188,17 @@ struct DataLayout
uint64_t result = 0;
for (auto i = 0; i < NUM_BLOCKS; i++)
{
BOOST_ASSERT(blocks[i].entry_align > 0);
result += 2 * sizeof(CANARY) + GetBlockSize((BlockID)i) + blocks[i].entry_align;
result += 2 * sizeof(CANARY) + GetBlockSize(static_cast<BlockID>(i)) + BLOCK_ALIGNMENT;
}
return result;
}
// \brief Fit aligned storage in buffer.
// Interface Similar to [ptr.align] but omits space computation.
// The method can be removed and changed directly to an std::align
// function call after dropping gcc < 5 support.
inline void *align(std::size_t align, std::size_t, void *&ptr) const noexcept
{
const auto intptr = reinterpret_cast<uintptr_t>(ptr);
const auto aligned = (intptr - 1u + align) & -align;
return ptr = reinterpret_cast<void *>(aligned);
}
inline void *GetAlignedBlockPtr(void *ptr, BlockID bid) const
{
for (auto i = 0; i < bid; i++)
{
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(blocks[i].entry_align, blocks[i].entry_size, ptr);
ptr = static_cast<char *>(ptr) + GetBlockSize((BlockID)i);
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
}
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(blocks[bid].entry_align, blocks[bid].entry_size, ptr);
return ptr;
}
template <typename T> inline T *GetBlockEnd(char *shared_memory, BlockID bid) const
{
auto begin = GetBlockPtr<T>(shared_memory, bid);
return begin + GetBlockEntries(bid);
}
template <typename T, bool WRITE_CANARY = false>
inline T *GetBlockPtr(char *shared_memory, BlockID bid) const
{
static_assert(BLOCK_ALIGNMENT % std::alignment_of<T>::value == 0,
"Datatype does not fit alignment constraints.");
char *ptr = (char *)GetAlignedBlockPtr(shared_memory, bid);
if (WRITE_CANARY)
{
@ -258,6 +227,39 @@ struct DataLayout
return (T *)ptr;
}
private:
// Fit aligned storage in buffer to 64 bytes to conform with AVX 512 types
inline void *align(void *&ptr) const noexcept
{
const auto intptr = reinterpret_cast<uintptr_t>(ptr);
const auto aligned = (intptr - 1u + BLOCK_ALIGNMENT) & -BLOCK_ALIGNMENT;
return ptr = reinterpret_cast<void *>(aligned);
}
inline void *GetAlignedBlockPtr(void *ptr, BlockID bid) const
{
for (auto i = 0; i < bid; i++)
{
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(ptr);
ptr = static_cast<char *>(ptr) + GetBlockSize((BlockID)i);
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
}
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(ptr);
return ptr;
}
template <typename T> inline T *GetBlockEnd(char *shared_memory, BlockID bid) const
{
auto begin = GetBlockPtr<T>(shared_memory, bid);
return begin + GetBlockEntries(bid);
}
static constexpr std::size_t BLOCK_ALIGNMENT = 64;
std::array<Block, NUM_BLOCKS> blocks;
};
enum SharedDataType