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