NeoN
A framework for CFD software
Loading...
Searching...
No Matches
parallelAlgorithms.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#include <type_traits>
7
10
11namespace NeoN
12{
13
14
15template<typename ValueType>
16class Vector;
17
18
19// Concept to check if a callable is compatible with void(const size_t)
20template<typename Kernel>
21concept parallelForKernel = requires(Kernel t, size_t i) {
22 {
23 t(i)
24 } -> std::same_as<void>;
25};
26
27template<typename Executor, parallelForKernel Kernel>
29 [[maybe_unused]] const Executor& exec,
30 std::pair<localIdx, localIdx> range,
31 Kernel kernel,
32 std::string name = "parallelFor"
33)
34{
35 auto [start, end] = range;
36 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
37 {
38 for (localIdx i = start; i < end; i++)
39 {
40 kernel(i);
41 }
42 }
43 else
44 {
45 using runOn = typename Executor::exec;
46 Kokkos::parallel_for(
47 name,
48 Kokkos::RangePolicy<runOn>(start, end),
49 KOKKOS_LAMBDA(const localIdx i) { kernel(i); }
50 );
51 }
52}
53
54
55template<parallelForKernel Kernel>
57 const NeoN::Executor& exec,
58 std::pair<localIdx, localIdx> range,
59 Kernel kernel,
60 std::string name = "parallelFor"
61)
62{
63 std::visit([&](const auto& e) { parallelFor(e, range, kernel, name); }, exec);
64}
65
66// Concept to check if a callable is compatible with ValueType(const size_t)
67template<typename Kernel, typename ValueType>
68concept parallelForVectorKernel = requires(Kernel t, ValueType val, size_t i) {
69 {
70 t(i)
71 } -> std::same_as<ValueType>;
72};
73
74template<typename Executor, typename ValueType, parallelForVectorKernel<ValueType> Kernel>
76 [[maybe_unused]] const Executor& exec,
77 Vector<ValueType>& field,
78 Kernel kernel,
79 std::string name = "parallelFor"
80)
81{
82 auto view = field.view();
83 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
84 {
85 localIdx fieldSize = field.size();
86 for (localIdx i = 0; i < fieldSize; i++)
87 {
88 view[i] = kernel(i);
89 }
90 }
91 else
92 {
93 using runOn = typename Executor::exec;
94 Kokkos::parallel_for(
95 name,
96 Kokkos::RangePolicy<runOn>(0, field.size()),
97 KOKKOS_LAMBDA(const localIdx i) { view[i] = kernel(i); }
98 );
99 }
100}
101
102template<typename ValueType, parallelForVectorKernel<ValueType> Kernel>
103void parallelFor(Vector<ValueType>& field, Kernel kernel, std::string name = "parallelFor")
104{
105 std::visit([&](const auto& e) { parallelFor(e, field, kernel, name); }, field.exec());
106}
107
108template<typename Executor, typename Kernel, typename T>
110 [[maybe_unused]] const Executor& exec,
111 std::pair<localIdx, localIdx> range,
112 Kernel kernel,
113 T& value
114)
115{
116 auto [start, end] = range;
117 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
118 {
119 for (localIdx i = start; i < end; i++)
120 {
121 if constexpr (Kokkos::is_reducer<T>::value)
122 {
123 kernel(i, value.reference());
124 }
125 else
126 {
127 kernel(i, value);
128 }
129 }
130 }
131 else
132 {
133 using runOn = typename Executor::exec;
134 Kokkos::parallel_reduce(
135 "parallelReduce", Kokkos::RangePolicy<runOn>(start, end), kernel, value
136 );
137 }
138}
139
140template<typename Kernel, typename T>
142 const NeoN::Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel, T& value
143)
144{
145 std::visit([&](const auto& e) { parallelReduce(e, range, kernel, value); }, exec);
146}
147
148
149template<typename Executor, typename ValueType, typename Kernel, typename T>
151 [[maybe_unused]] const Executor& exec, Vector<ValueType>& field, Kernel kernel, T& value
152)
153{
154 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
155 {
156 localIdx fieldSize = field.size();
157 for (localIdx i = 0; i < fieldSize; i++)
158 {
159 if constexpr (Kokkos::is_reducer<T>::value)
160 {
161 kernel(i, value.reference());
162 }
163 else
164 {
165 kernel(i, value);
166 }
167 }
168 }
169 else
170 {
171 using runOn = typename Executor::exec;
172 Kokkos::parallel_reduce(
173 "parallelReduce", Kokkos::RangePolicy<runOn>(0, field.size()), kernel, value
174 );
175 }
176}
177
178template<typename ValueType, typename Kernel, typename T>
179void parallelReduce(Vector<ValueType>& field, Kernel kernel, T& value)
180{
181 std::visit([&](const auto& e) { parallelReduce(e, field, kernel, value); }, field.exec());
182}
183
184template<typename Executor, typename Kernel>
186 [[maybe_unused]] const Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel
187)
188{
189 auto [start, end] = range;
190 using runOn = typename Executor::exec;
191 Kokkos::parallel_scan("parallelScan", Kokkos::RangePolicy<runOn>(start, end), kernel);
192}
193
194template<typename Kernel>
195void parallelScan(const NeoN::Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel)
196{
197 std::visit([&](const auto& e) { parallelScan(e, range, kernel); }, exec);
198}
199
200template<typename Executor, typename Kernel, typename ReturnType>
202 [[maybe_unused]] const Executor& exec,
203 std::pair<localIdx, localIdx> range,
204 Kernel kernel,
205 ReturnType& returnValue
206)
207{
208 auto [start, end] = range;
209 using runOn = typename Executor::exec;
210 Kokkos::parallel_scan(
211 "parallelScan", Kokkos::RangePolicy<runOn>(start, end), kernel, returnValue
212 );
213}
214
215template<typename Kernel, typename ReturnType>
217 const NeoN::Executor& exec,
218 std::pair<localIdx, localIdx> range,
219 Kernel kernel,
220 ReturnType& returnValue
221)
222{
223 std::visit([&](const auto& e) { parallelScan(e, range, kernel, returnValue); }, exec);
224}
225
226
227} // 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
localIdx size() const
Gets the size of the field.
Definition vector.hpp:364
const Executor & exec() const
Gets the executor associated with the field.
Definition vector.hpp:358
View< ValueType > view() &&=delete
void parallelFor(const Executor &exec, std::pair< localIdx, localIdx > range, Kernel kernel, std::string name="parallelFor")
int32_t localIdx
Definition label.hpp:30
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:16
void parallelReduce(const Executor &exec, std::pair< localIdx, localIdx > range, Kernel kernel, T &value)
const std::string & name(const NeoN::Document &doc)
Retrieves the name of a Document.
void parallelScan(const Executor &exec, std::pair< localIdx, localIdx > range, Kernel kernel)