25#ifndef CPU_SIMD_COLUMN_H
26#define CPU_SIMD_COLUMN_H
36#include <asm/unistd_64.h>
56 std::unique_ptr<T[]> _data;
63 _data(new T[count] {})
72 _data(rhs._data.release())
77 _data(new T[_count] {})
79 std::copy(rhs._data.get(),
80 rhs._data.get() + _count,
88 std::unique_ptr<T[]>
data = std::unique_ptr<T[]>(
new T[count] { });
89 std::copy(_data.get(), _data.get() + std::min(_count, count),
data.get());
126 bool*
getBlock(std::size_t iBlock, std::size_t& sizeBlock,
bool loadingMode)
override;
136 const std::size_t page_size = sysconf(_SC_PAGESIZE);
137 const std::size_t size = ((count *
sizeof(T) - 1) / page_size + 1) * page_size;
138 const std::size_t volume = size /
sizeof(T);
140 if (size % page_size != 0) {
141 throw std::invalid_argument(
"Buffer size must be multiple of PAGE_SIZE");
156 const std::ptrdiff_t _count;
157 const std::size_t _size;
159 std::uint8_t* _buffer;
164 std::ptrdiff_t _shift;
171 _size(_count * sizeof(T)),
174 #ifdef __NR_memfd_create
177 const int shm_file = syscall(__NR_memfd_create,
"openlb", MFD_CLOEXEC);
179 std::string shm_path =
"/openlb_block_XXXXXX";
180 const int shm_name = mkstemp(
const_cast<char*
>(shm_path.data()));
181 if (shm_name != -1) {
182 throw std::runtime_error(
"Could not generate unique shared memory object name");
185 const int shm_file = shm_open(shm_path.c_str(), O_CREAT | O_RDWR | O_EXCL | O_CLOEXEC, S_IRUSR | S_IWUSR);
186 shm_unlink(shm_path.c_str());
188 if (shm_file == -1) {
189 throw std::runtime_error(
"Failed to create shared memory object");
193 if (ftruncate(shm_file, _size) == -1) {
194 throw std::runtime_error(
"Failed to resize shared memory object");
198 _buffer =
static_cast<std::uint8_t*
>(
199 mmap(NULL, 2 * _size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
202 mmap(_buffer, _size,
PROT_RW, MAP_SHARED | MAP_FIXED, shm_file, 0);
203 mmap(_buffer + _size, _size,
PROT_RW, MAP_SHARED | MAP_FIXED, shm_file, 0);
206 _base =
reinterpret_cast<T*
>(_buffer);
212 munmap(_buffer, 2 * _size);
238 if (_shift >= _count) {
241 else if (_shift < 0) {
249 throw std::logic_error(
"Cyclic column can not be resized");
259 bool*
getBlock(std::size_t iBlock, std::size_t& sizeBlock,
bool loadingMode)
override;
293 return indices.
size() *
sizeof(T);
298 std::uint8_t* buffer)
const
300 if (meta::is_aligned<T>(buffer)) {
301 T* target =
reinterpret_cast<T*
>(buffer);
304 for (std::size_t i=0;
314 *(target++) = _column[indices[i]];
317 std::uint8_t* target = buffer;
318 for (
CellID index : indices) {
319 std::memcpy(target,
reinterpret_cast<const void*
>(&_column[index]),
sizeof(T));
323 return indices.
size() *
sizeof(T);
328 const std::uint8_t* buffer)
330 if (meta::is_aligned<T>(buffer)) {
331 const T* source =
reinterpret_cast<const T*
>(buffer);
334 for (std::size_t i=0;
344 _column[indices[i]] = *(source++);
347 const std::uint8_t* source = buffer;
348 for (
CellID index : indices) {
349 std::memcpy(
reinterpret_cast<void*
>(&_column[index]), source,
sizeof(T));
353 return indices.
size() *
sizeof(T);
ConcreteCommunicatable(cpu::simd::CyclicColumn< T > &column)
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const
Serialize data at locations indices to buffer
std::size_t size(ConstSpan< CellID > indices) const
Get serialized size for data at locations indices
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer)
Deserialize data at locations indices to buffer
Base class for serializable objects of constant size. For dynamic size use BufferSerializable.
Plain column for SIMD CPU targets.
Column(const Column< T > &rhs)
Column(std::size_t count)
Column(Column< T > &&rhs)
void resize(std::size_t count)
virtual ~Column()=default
std::size_t getSerializableSize() const override
Binary size for the serializer.
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
void setProcessingContext(ProcessingContext)
T & operator[](std::size_t i) override
const T & operator[](std::size_t i) const override
Virtual memory based cyclic column for usage in ColumnVector.
void rotate(std::ptrdiff_t offset)
const T & operator[](std::size_t i) const override
void setProcessingContext(ProcessingContext)
CyclicColumn(std::size_t count)
T & operator[](std::size_t i) override
void resize(std::size_t count)
std::size_t getSerializableSize() const override
Binary size for the serializer.
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
std::size_t getPageAlignedCount(std::size_t count)
void store(T *target, Pack< T > value)
Top level namespace for all of OpenLB.
std::uint32_t CellID
Type for sequential block-local cell indices.
ProcessingContext
OpenLB processing contexts.
Platform
OpenLB execution targets.
@ CPU_SIMD
Basic scalar CPU.
Abstract declarator of Column-like storage.
Abstract declarator of cyclic Column-like storage.
Specializable declarator for concrete implementations of abstract storage types.