alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
SharedStorage.hpp
Go to the documentation of this file.
1/* Copyright 2022 Jeffrey Kelling, Rene Widera, Bernhard Manfred Gruber
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
8
9#include <algorithm>
10#include <array>
11#include <cstdint>
12#include <functional>
13#include <limits>
14#include <type_traits>
15
16#ifndef ALPAKA_BLOCK_SHARED_DYN_MEMBER_ALLOC_KIB
17# define ALPAKA_BLOCK_SHARED_DYN_MEMBER_ALLOC_KIB 64u
18#endif
19
21{
22 //! Implementation of static block shared memory provider.
23 //!
24 //! externally allocated fixed-size memory, likely provided by BlockSharedMemDynMember.
25 template<std::size_t TMinDataAlignBytes>
27 {
28 struct alignas(TMinDataAlignBytes) MetaData
29 {
30 //! Unique id if the next data chunk.
31 size_t id = 0u;
32 //! Offset to the next meta data header, relative to m_mem.
33 //! To access the meta data header the offset must by aligned first.
34 std::uint32_t offset = 0u;
35 };
36
37 static constexpr std::uint32_t metaDataSize = sizeof(MetaData);
38
39 public:
40 SharedStorage() = default;
41
42 template<typename T>
43 void alloc(size_t id) const
44 {
45 // Add meta data chunk in front of the user data
49
50 // Allocate variable
53
54 // Update meta data with id and offset for the allocated variable.
55 meta->id = id;
56 meta->offset = m_allocdBytes;
57 }
58
59 template<typename T>
60 void allocDynamic(size_t id, uint32_t numBytes) const
61 {
62 // Add meta data chunk in front of the user data
66
67 // Allocate variable
70
71 // Update meta data with id and offset for the allocated variable.
72 meta->id = id;
73 meta->offset = m_allocdBytes;
74 }
75
76 //! Give the pointer to an exiting variable
77 //!
78 //! @tparam T type of the variable
79 //! @param id unique id of the variable
80 //! @return nullptr if variable with id not exists
81 template<typename T>
82 auto getVarPtr(size_t id) const -> T*
83 {
84 // Offset in bytes to the next unaligned meta data header behind the variable.
85 std::uint32_t off = 0;
86
87 // Iterate over allocated data only
88 while(off < m_allocdBytes)
89 {
90 // Adjust offset to be aligned
91 std::uint32_t const alignedMetaDataOffset
92 = varChunkEnd<MetaData>(off, sizeof(MetaData)) - static_cast<std::uint32_t>(sizeof(MetaData));
94 (alignedMetaDataOffset + static_cast<std::uint32_t>(sizeof(MetaData))) <= m_allocdBytes);
95 auto* metaDataPtr = reinterpret_cast<MetaData*>(data() + alignedMetaDataOffset);
96 off = metaDataPtr->offset;
97
98 if(metaDataPtr->id == id)
99 return reinterpret_cast<T*>(&data()[off - sizeof(T)]);
100 }
101
102 // Variable not found.
103 return nullptr;
104 }
105
106 //! Get last allocated variable.
107 template<typename T>
108 auto getLatestVarPtr() const -> T*
109 {
110 return reinterpret_cast<T*>(&data()[m_allocdBytes - sizeof(T)]);
111 }
112
113 private:
114 uint8_t* data() const
115 {
116 return m_data.data();
117 }
118
119 //! Byte offset to the end of the memory chunk
120 //!
121 //! Calculate bytes required to store a type with a aligned starting address in m_mem.
122 //! Start offset to the origin of the user data chunk can be calculated with `result - sizeof(T)`.
123 //! The padding is always before the origin of the user data chunk and can be zero byte.
124 //!
125 //! \tparam T type should fit into the chunk
126 //! \param byteOffset Current byte offset.
127 //! \param byteOffset Number of bytes to allocate, should be at least sizeof(T).
128 //! \result Byte offset to the end of the data chunk, relative to m_mem..
129 template<typename T>
130 auto varChunkEnd(uint32_t byteOffset, uint32_t numBytes) const -> std::uint32_t
131 {
132 auto const ptr = reinterpret_cast<std::size_t>(data() + byteOffset);
133 constexpr size_t align = std::max(TMinDataAlignBytes, alignof(T));
134 std::size_t const newPtrAdress = ((ptr + align - 1u) / align) * align + numBytes;
135 return static_cast<uint32_t>(newPtrAdress - reinterpret_cast<std::size_t>(data()));
136 }
137
138 static constexpr std::uint32_t totalSharedBytes
139 = static_cast<std::uint32_t>(ALPAKA_BLOCK_SHARED_DYN_MEMBER_ALLOC_KIB << 10u);
140 //! Memory layout
141 //! |Header|Padding|Variable|Padding|Header|....uninitialized Data ....
142 //! Size of padding can be zero if data after padding is already aligned.
143 mutable std::array<uint8_t, totalSharedBytes> m_data;
144
145 //! Offset in bytes relative to m_mem to next free data area.
146 //! The last aligned before the free area is always a meta data header.
147 mutable std::uint32_t m_allocdBytes = 0u;
148 };
149} // namespace alpaka::onAcc::cpu::detail
#define ALPAKA_ASSERT_ACC(...)
ALPAKA_ASSERT_ACC is an assert-like macro.
Definition Assert.hpp:53
#define ALPAKA_BLOCK_SHARED_DYN_MEMBER_ALLOC_KIB
void allocDynamic(size_t id, uint32_t numBytes) const
auto varChunkEnd(uint32_t byteOffset, uint32_t numBytes) const -> std::uint32_t
auto getVarPtr(size_t id) const -> T *
Give the pointer to an exiting variable.
std::uint32_t offset
Offset to the next meta data header, relative to m_mem. To access the meta data header the offset mus...