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 parallelForContainerKernel = requires(Kernel t, ValueType val, size_t i) {
69 {
70 t(i)
71 } -> std::same_as<ValueType>;
72};
73
74template<
75 typename Executor,
76 template<typename>
77 class ContType,
78 typename ValueType,
81 [[maybe_unused]] const Executor& exec,
82 ContType<ValueType>& container,
83 Kernel kernel,
84 std::string name = "parallelFor"
85)
86{
87 auto view = container.view();
88 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
89 {
90 for (localIdx i = 0; i < view.size(); i++)
91 {
92 view[i] = kernel(i);
93 }
94 }
95 else
96 {
97 using runOn = typename Executor::exec;
98 Kokkos::parallel_for(
99 name,
100 Kokkos::RangePolicy<runOn>(0, view.size()),
101 KOKKOS_LAMBDA(const localIdx i) { view[i] = kernel(i); }
102 );
103 }
104}
105
106template<
107 template<typename>
108 class ContType,
109 typename ValueType,
110 parallelForContainerKernel<ValueType> Kernel>
111void parallelFor(ContType<ValueType>& cont, Kernel kernel, std::string name = "parallelFor")
112{
113 std::visit([&](const auto& e) { parallelFor(e, cont, kernel, name); }, cont.exec());
114}
115
116template<typename Executor, typename Kernel, typename T>
118 [[maybe_unused]] const Executor& exec,
119 std::pair<localIdx, localIdx> range,
120 Kernel kernel,
121 T& value
122)
123{
124 auto [start, end] = range;
125 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
126 {
127 for (localIdx i = start; i < end; i++)
128 {
129 if constexpr (Kokkos::is_reducer<T>::value)
130 {
131 kernel(i, value.reference());
132 }
133 else
134 {
135 kernel(i, value);
136 }
137 }
138 }
139 else
140 {
141 using runOn = typename Executor::exec;
142 Kokkos::parallel_reduce(
143 "parallelReduce", Kokkos::RangePolicy<runOn>(start, end), kernel, value
144 );
145 }
146}
147
148template<typename Kernel, typename T>
150 const NeoN::Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel, T& value
151)
152{
153 std::visit([&](const auto& e) { parallelReduce(e, range, kernel, value); }, exec);
154}
155
156
157template<typename Executor, typename ValueType, typename Kernel, typename T>
159 [[maybe_unused]] const Executor& exec, Vector<ValueType>& field, Kernel kernel, T& value
160)
161{
162 if constexpr (std::is_same<std::remove_reference_t<Executor>, SerialExecutor>::value)
163 {
164 localIdx fieldSize = field.size();
165 for (localIdx i = 0; i < fieldSize; i++)
166 {
167 if constexpr (Kokkos::is_reducer<T>::value)
168 {
169 kernel(i, value.reference());
170 }
171 else
172 {
173 kernel(i, value);
174 }
175 }
176 }
177 else
178 {
179 using runOn = typename Executor::exec;
180 Kokkos::parallel_reduce(
181 "parallelReduce", Kokkos::RangePolicy<runOn>(0, field.size()), kernel, value
182 );
183 }
184}
185
186template<typename ValueType, typename Kernel, typename T>
187void parallelReduce(Vector<ValueType>& field, Kernel kernel, T& value)
188{
189 std::visit([&](const auto& e) { parallelReduce(e, field, kernel, value); }, field.exec());
190}
191
192template<typename Executor, typename Kernel>
194 [[maybe_unused]] const Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel
195)
196{
197 auto [start, end] = range;
198 using runOn = typename Executor::exec;
199 Kokkos::parallel_scan("parallelScan", Kokkos::RangePolicy<runOn>(start, end), kernel);
200}
201
202template<typename Kernel>
203void parallelScan(const NeoN::Executor& exec, std::pair<localIdx, localIdx> range, Kernel kernel)
204{
205 std::visit([&](const auto& e) { parallelScan(e, range, kernel); }, exec);
206}
207
208template<typename Executor, typename Kernel, typename ReturnType>
210 [[maybe_unused]] const Executor& exec,
211 std::pair<localIdx, localIdx> range,
212 Kernel kernel,
213 ReturnType& returnValue
214)
215{
216 auto [start, end] = range;
217 using runOn = typename Executor::exec;
218 Kokkos::parallel_scan(
219 "parallelScan", Kokkos::RangePolicy<runOn>(start, end), kernel, returnValue
220 );
221}
222
223template<typename Kernel, typename ReturnType>
225 const NeoN::Executor& exec,
226 std::pair<localIdx, localIdx> range,
227 Kernel kernel,
228 ReturnType& returnValue
229)
230{
231 std::visit([&](const auto& e) { parallelScan(e, range, kernel, returnValue); }, exec);
232}
233
234} // 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:28
localIdx size() const
Gets the size of the field.
Definition vector.hpp:233
const Executor & exec() const
Gets the executor associated with the field.
Definition vector.hpp:227
Definition array.hpp:19
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)