NeoN
WIP Prototype of a modern OpenFOAM core
Loading...
Searching...
No Matches
vector.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2023 NeoN authors
3#pragma once
4
5#include <Kokkos_Core.hpp>
6
7#include "NeoN/core/error.hpp"
11#include "NeoN/core/view.hpp"
14
15#include <variant>
16#include <vector>
17
18
19namespace NeoN
20{
21
22namespace detail
23{
32template<typename ValueType>
33auto deepCopyVisitor(localIdx ssize, const ValueType* srcPtr, ValueType* dstPtr)
34{
35 size_t size = static_cast<size_t>(ssize);
36 return [size, srcPtr, dstPtr](const auto& srcExec, const auto& dstExec)
37 {
38 Kokkos::deep_copy(
39 dstExec.createKokkosView(dstPtr, size), srcExec.createKokkosView(srcPtr, size)
40 );
41 };
42}
43}
44
51template<typename ValueType>
52class Vector
53{
54
55public:
56
57 using VectorValueType = ValueType;
58
64 Vector(const Executor& exec, localIdx size) : size_(size), data_(nullptr), exec_(exec)
65 {
66 void* ptr = nullptr;
67 std::visit(
68 [&ptr, size](const auto& concreteExec)
69 { ptr = concreteExec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
70 exec_
71 );
72 data_ = static_cast<ValueType*>(ptr);
73 }
74
83 const Executor& exec,
84 const ValueType* in,
86 Executor hostExec = SerialExecutor()
87 )
88 : size_(size), data_(nullptr), exec_(exec)
89 {
90 void* ptr = nullptr;
91 std::visit(
92 [&ptr, size](const auto& concreteExec)
93 { ptr = concreteExec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
94 exec_
95 );
96 data_ = static_cast<ValueType*>(ptr);
97 std::visit(detail::deepCopyVisitor<ValueType>(size_, in, data_), hostExec, exec_);
98 }
99
106 Vector(const Executor& exec, localIdx size, ValueType value)
107 : size_(size), data_(nullptr), exec_(exec)
108 {
109 void* ptr = nullptr;
110 std::visit(
111 [&ptr, size](const auto& execu)
112 { ptr = execu.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
113 exec_
114 );
115 data_ = static_cast<ValueType*>(ptr);
116 NeoN::fill(*this, value);
117 }
118
124 Vector(const Executor& exec, std::vector<ValueType> in)
125 : Vector(exec, in.data(), static_cast<localIdx>(in.size()))
126 {}
127
134 : Vector(exec, in.data(), in.size(), in.exec())
135 {}
136
141 Vector(const Vector<ValueType>& rhs) : Vector(rhs.exec(), rhs.data(), rhs.size(), rhs.exec()) {}
142
147 Vector(Vector<ValueType>&& rhs) noexcept : size_(rhs.size_), data_(rhs.data_), exec_(rhs.exec_)
148 {
149 rhs.data_ = nullptr;
150 rhs.size_ = 0;
151 }
152
157 {
158 std::visit([this](const auto& exec) { exec.free(data_); }, exec_);
159 data_ = nullptr;
160 }
161
167 template<typename func>
168 void apply(func f)
169 {
170 map(*this, f);
171 }
172
178 [[nodiscard]] Vector<ValueType> copyToExecutor(Executor dstExec) const
179 {
180 if (dstExec == exec_) return *this;
181
182 Vector<ValueType> result(dstExec, size_);
183 std::visit(detail::deepCopyVisitor(size_, data_, result.data()), exec_, dstExec);
184
185 return result;
186 }
187
192 [[nodiscard]] Vector<ValueType> copyToHost() const { return copyToExecutor(SerialExecutor()); }
193
203 {
205 result.size() == size_, "Parsed Vector size not the same as current field size"
206 );
207 result = copyToExecutor(SerialExecutor());
208 }
209
210 // ensures no return of device address on host --> invalid memory access
211 ValueType& operator[](const localIdx i) = delete;
212
213 // ensures no return of device address on host --> invalid memory access
214 const ValueType& operator[](const localIdx i) const = delete;
215
220 void operator=(const ValueType& rhs) { fill(*this, rhs); }
221
229 {
230 NF_ASSERT(exec_ == rhs.exec_, "Executors are not the same");
231 if (this->size() != rhs.size())
232 {
233 this->resize(rhs.size());
234 }
235 setVector(*this, rhs.view());
236 }
237
244 {
245 validateOtherVector(rhs);
246 add(*this, rhs);
247 return *this;
248 }
249
256 {
257 validateOtherVector(rhs);
258 sub(*this, rhs);
259 return *this;
260 }
261
268 {
269 validateOtherVector(rhs);
270 Vector<ValueType> result(exec_, size_);
271 result = *this;
272 mul(result, rhs);
273 return result;
274 }
275
282 [[nodiscard]] Vector<ValueType> operator*(const scalar rhs)
283 {
284 Vector<ValueType> result(exec_, size_);
285 result = *this;
286 scalarMul(result, rhs);
287 return result;
288 }
289
296 {
297 validateOtherVector(rhs);
298 Vector<ValueType>& result = *this;
299 mul(result, rhs);
300 return result;
301 }
302
309 {
310 Vector<ValueType>& result = *this;
311 scalarMul(result, rhs);
312 return result;
313 }
314
319 void resize(const localIdx size)
320 {
321 void* ptr = nullptr;
322 if (!empty())
323 {
324 std::visit(
325 [this, &ptr, size](const auto& exec)
326 { ptr = exec.realloc(this->data_, static_cast<size_t>(size) * sizeof(ValueType)); },
327 exec_
328 );
329 }
330 else
331 {
332 std::visit(
333 [&ptr, size](const auto& exec)
334 { ptr = exec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
335 exec_
336 );
337 }
338 data_ = static_cast<ValueType*>(ptr);
339 size_ = size;
340 }
341
346 [[nodiscard]] ValueType* data() { return data_; }
347
352 [[nodiscard]] const ValueType* data() const { return data_; }
353
358 [[nodiscard]] const Executor& exec() const { return exec_; }
359
364 [[nodiscard]] localIdx size() const { return size_; }
365
370 [[nodiscard]] label ssize() const { return static_cast<label>(size_); }
371
376 [[nodiscard]] bool empty() const { return size() == 0; }
377
378 // return of a temporary --> invalid memory access
379 View<ValueType> view() && = delete;
380
381 // return of a temporary --> invalid memory access
382 View<const ValueType> view() const&& = delete;
383
388 [[nodiscard]] View<ValueType> view() &
389 {
390 return View<ValueType>(data_, static_cast<size_t>(size_));
391 }
392
397 [[nodiscard]] View<const ValueType> view() const&
398 {
399 return View<const ValueType>(data_, static_cast<size_t>(size_));
400 }
401
402 // return of a temporary --> invalid memory access
403 [[nodiscard]] View<ValueType> view(std::pair<localIdx, localIdx> range) && = delete;
404
405 // return of a temporary --> invalid memory access
406 [[nodiscard]] View<const ValueType> view(std::pair<localIdx, localIdx> range) const&& = delete;
407
412 [[nodiscard]] View<ValueType> view(std::pair<localIdx, localIdx> range) &
413 {
414 return View<ValueType>(
415 data_ + range.first, static_cast<size_t>(range.second - range.first)
416 );
417 }
418
423 [[nodiscard]] View<const ValueType> view(std::pair<localIdx, localIdx> range) const&
424 {
426 data_ + range.first, static_cast<size_t>(range.second - range.first)
427 );
428 }
429
434 [[nodiscard]] std::pair<localIdx, localIdx> range() const { return {0, size()}; }
435
436private:
437
438 localIdx size_ {0};
439 ValueType* data_ {nullptr};
440 const Executor exec_;
441
446 void validateOtherVector(const Vector<ValueType>& rhs) const
447 {
448 NF_DEBUG_ASSERT(size() == rhs.size(), "Vectors are not the same size.");
449 NF_DEBUG_ASSERT(exec() == rhs.exec(), "Executors are not the same.");
450 }
451};
452
459template<typename T>
460[[nodiscard]] Vector<T> operator+(Vector<T> lhs, const Vector<T>& rhs)
461{
462 lhs += rhs;
463 return lhs;
464}
465
472template<typename T>
473[[nodiscard]] Vector<T> operator-(Vector<T> lhs, const Vector<T>& rhs)
474{
475 lhs -= rhs;
476 return lhs;
477}
478
479} // namespace NeoN
Reference executor for serial CPU execution.
A class to contain the data and executors for a field and define some basic operations.
Definition vector.hpp:53
Vector(const Executor &exec, const ValueType *in, localIdx size, Executor hostExec=SerialExecutor())
Create a Vector with a given size from existing memory on an executor.
Definition vector.hpp:82
Vector(Vector< ValueType > &&rhs) noexcept
Move constructor, moves the data from the parsed field to the new field.
Definition vector.hpp:147
ValueType & operator[](const localIdx i)=delete
Vector(const Vector< ValueType > &rhs)
Copy constructor, creates a new field with the same size and data as the parsed field.
Definition vector.hpp:141
Vector< ValueType > & operator*=(const scalar rhs)
Arithmetic multiply-assignment operator, multiplies every cell in the field by a scalar and updates t...
Definition vector.hpp:308
localIdx size() const
Gets the size of the field.
Definition vector.hpp:364
Vector< ValueType > copyToExecutor(Executor dstExec) const
Copies the data to a new field on a specific executor.
Definition vector.hpp:178
Vector(const Executor &exec, const Vector< ValueType > &in)
Create a Vector as a copy of a Vector on a specified executor.
Definition vector.hpp:133
View< ValueType > view(std::pair< localIdx, localIdx > range) &
Gets a sub view of the field as a view.
Definition vector.hpp:412
ValueType * data()
Direct access to the underlying field data.
Definition vector.hpp:346
Vector(const Executor &exec, localIdx size, ValueType value)
Create a Vector with a given size on an executor and uniform value.
Definition vector.hpp:106
Vector< ValueType > & operator*=(const Vector< scalar > &rhs)
Arithmetic multiply operator, multiplies this field by another field element-wise.
Definition vector.hpp:295
std::pair< localIdx, localIdx > range() const
Gets the range of the field.
Definition vector.hpp:434
View< const ValueType > view(std::pair< localIdx, localIdx > range) const &&=delete
label ssize() const
Gets the size of the field.
Definition vector.hpp:370
Vector(const Executor &exec, localIdx size)
Create an uninitialized Vector with a given size on an executor.
Definition vector.hpp:64
void operator=(const ValueType &rhs)
Assignment operator, Sets the field values to that of the passed value.
Definition vector.hpp:220
View< const ValueType > view() const &
Gets the field as a view.
Definition vector.hpp:397
View< const ValueType > view(std::pair< localIdx, localIdx > range) const &
Gets a sub view of the field as a view.
Definition vector.hpp:423
const ValueType * data() const
Direct access to the underlying field data.
Definition vector.hpp:352
void resize(const localIdx size)
Resizes the field to a new size.
Definition vector.hpp:319
bool empty() const
Checks if the field is empty.
Definition vector.hpp:376
void apply(func f)
applies a functor, transformation, to the field
Definition vector.hpp:168
const Executor & exec() const
Gets the executor associated with the field.
Definition vector.hpp:358
Vector< ValueType > & operator+=(const Vector< ValueType > &rhs)
Arithmetic add operator, addition of a second field.
Definition vector.hpp:243
~Vector()
Destroy the Vector object.
Definition vector.hpp:156
View< ValueType > view(std::pair< localIdx, localIdx > range) &&=delete
ValueType VectorValueType
Definition vector.hpp:57
Vector(const Executor &exec, std::vector< ValueType > in)
Create a Vector from a given vector of values on an executor.
Definition vector.hpp:124
void copyToHost(Vector< ValueType > &result)
Copies the data (from anywhere) to a parsed host field.
Definition vector.hpp:202
Vector< ValueType > operator*(const Vector< scalar > &rhs)
Arithmetic multiply operator, multiply by a second field.
Definition vector.hpp:267
View< ValueType > view() &&=delete
Vector< ValueType > copyToHost() const
Returns a copy of the field back to the host.
Definition vector.hpp:192
Vector< ValueType > & operator-=(const Vector< ValueType > &rhs)
Arithmetic subtraction operator, subtraction by a second field.
Definition vector.hpp:255
const ValueType & operator[](const localIdx i) const =delete
void operator=(const Vector< ValueType > &rhs)
Assignment operator, Sets the field values to that of the parsed field.
Definition vector.hpp:228
Vector< ValueType > operator*(const scalar rhs)
Arithmetic multiply operator, multiplies every cell in the field by a scalar.
Definition vector.hpp:282
View< const ValueType > view() const &&=delete
#define NF_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false.
Definition error.hpp:142
#define NF_DEBUG_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false (only in debu...
Definition error.hpp:211
auto deepCopyVisitor(localIdx ssize, const ValueType *srcPtr, ValueType *dstPtr)
A helper function to simplify the common pattern of copying between and to executor.
Definition vector.hpp:33
void map(Vector< T > &a, const Inner inner, std::pair< localIdx, localIdx > range={0, 0})
Map a field using a specific executor.
int32_t localIdx
Definition label.hpp:30
void mul(Vector< ValueType > &a, const Vector< std::type_identity_t< ValueType > > &b)
void add(Vector< ValueType > &a, const Vector< std::type_identity_t< ValueType > > &b)
void fill(Vector< ValueType > &a, const std::type_identity_t< ValueType > value, std::pair< localIdx, localIdx > range={0, 0})
Fill the field with a scalar value using a specific executor.
Vector< T > operator+(Vector< T > lhs, const Vector< T > &rhs)
Arithmetic add operator, addition of two fields.
Definition vector.hpp:460
Vector< T > operator-(Vector< T > lhs, const Vector< T > &rhs)
Arithmetic subtraction operator, subtraction one field from another.
Definition vector.hpp:473
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:16
float scalar
Definition scalar.hpp:14
void setVector(Vector< ValueType > &a, const View< const std::type_identity_t< ValueType > > b, std::pair< localIdx, localIdx > range={0, 0})
Set the field with a view of values using a specific executor.
void sub(Vector< ValueType > &a, const Vector< std::type_identity_t< ValueType > > &b)
void scalarMul(Vector< ValueType > &a, const scalar value)
int32_t label
Definition label.hpp:24