alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
TaskKernelCpuOmp2Blocks.hpp
Go to the documentation of this file.
1/* Copyright 2026 Benjamin Worpitz, Bert Wesarg, René Widera, Sergei Bastrakov, Bernhard Manfred Gruber, Andrea Bocci
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
7// Specialized traits.
10#include "alpaka/dim/Traits.hpp"
11#include "alpaka/idx/Traits.hpp"
13
14// Implementation details.
16#include "alpaka/core/Decay.hpp"
18#include "alpaka/dev/DevCpu.hpp"
19#include "alpaka/idx/MapIdx.hpp"
24
25#include <functional>
26#include <stdexcept>
27#include <string>
28#include <tuple>
29#include <type_traits>
30#include <utility>
31#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
32# include <iostream>
33#endif
34
35#ifdef ALPAKA_ACC_CPU_B_OMP2_T_SEQ_ENABLED
36
37# if ALPAKA_COMP_CLANG
38# pragma clang diagnostic push
39# pragma clang diagnostic ignored "-Wswitch-default"
40# endif
41
42# if _OPENMP < 200203
43# error If ALPAKA_ACC_CPU_B_OMP2_T_SEQ_ENABLED is set, the compiler has to support OpenMP 2.0 or higher!
44# endif
45
46# include <omp.h>
47
48namespace alpaka
49{
50 namespace detail
51 {
52 //! Executor of parallel OpenMP loop with the given schedule
53 //!
54 //! Is explicitly specialized for all supported schedule kinds to help code optimization by compilers.
55 //!
56 //! \tparam TKernel The kernel type.
57 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
58 //! \tparam TScheduleKind The schedule kind value.
59 template<typename TKernel, typename TSchedule, omp::Schedule::Kind TScheduleKind>
61
62 //! Executor of parallel OpenMP loop with no schedule set
63 //!
64 //! Does not use chunk size.
65 //!
66 //! \tparam TKernel The kernel type.
67 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
68 template<typename TKernel, typename TSchedule>
69 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::NoSchedule>
70 {
71 //! Run parallel OpenMP loop
72 //!
73 //! \tparam TLoopBody The loop body functor type.
74 //! \tparam TIdx The index type.
75 //!
76 //! \param loopBody The loop body functor instance, takes iteration index as input.
77 //! \param numIterations The number of loop iterations.
78 template<typename TLoopBody, typename TIdx>
80 TKernel const&,
81 TLoopBody&& loopBody,
82 TIdx const numIterations,
83 TSchedule const&)
84 {
85# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
86 // header.
87 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
88 std::intmax_t i;
89# pragma omp for nowait
90 for(i = 0; i < iNumBlocksInGrid; ++i)
91# else
92# pragma omp for nowait
93 for(TIdx i = 0; i < numIterations; ++i)
94# endif
95 {
96 // Make another lambda to work around #1288
97 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
98 wrappedLoopBody(i);
99 }
100 }
101 };
102
103 /* Implementations for Static, Dynamic and Guided follow the same pattern.
104 * There are two specializations of ParallelForImpl for compile-time dispatch depending on whether the
105 * OmpSchedule trait is specialized.
106 * The no trait case is further compile-time dispatched with a helper ParallelForStaticImpl.
107 * It is based on whether ompScheduleChunkSize member is available.
108 */
109
110 //! Executor of parallel OpenMP loop with the static schedule
111 //!
112 //! Specialization for kernels specializing the OmpSchedule trait.
113 //!
114 //! \tparam TKernel The kernel type.
115 template<typename TKernel>
116 struct ParallelForImpl<TKernel, omp::Schedule, omp::Schedule::Static>
117 {
118 //! Run parallel OpenMP loop
119 //!
120 //! \tparam TLoopBody The loop body functor type.
121 //! \tparam TIdx The index type.
122 //!
123 //! \param loopBody The loop body functor instance, takes iteration index as input.
124 //! \param numIterations The number of loop iterations.
125 //! \param schedule The schedule object.
126 template<typename TLoopBody, typename TIdx>
128 TKernel const&,
129 TLoopBody&& loopBody,
130 TIdx const numIterations,
131 omp::Schedule const& schedule)
132 {
133# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
134 // header.
135 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
136 std::intmax_t i;
137# pragma omp for nowait schedule(static, schedule.chunkSize)
138 for(i = 0; i < iNumBlocksInGrid; ++i)
139# else
140# pragma omp for nowait schedule(static, schedule.chunkSize)
141 for(TIdx i = 0; i < numIterations; ++i)
142# endif
143 {
144 // Make another lambda to work around #1288
145 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
146 wrappedLoopBody(i);
147 }
148 }
149 };
150
151 //! Helper executor of parallel OpenMP loop with the static schedule
152 //!
153 //! Generel implementation is for TKernel types without member ompScheduleChunkSize.
154 //!
155 //! \tparam TKernel The kernel type.
156 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
157 template<typename TKernel, typename TSchedule, typename TSfinae = void>
159 {
160 //! Run parallel OpenMP loop
161 //!
162 //! \tparam TLoopBody The loop body functor type.
163 //! \tparam TIdx The index type.
164 //!
165 //! \param loopBody The loop body functor instance, takes iteration index as input.
166 //! \param numIterations The number of loop iterations.
167 template<typename TLoopBody, typename TIdx>
169 TKernel const&,
170 TLoopBody&& loopBody,
171 TIdx const numIterations,
172 TSchedule const&)
173 {
174# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
175 // header.
176 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
177 std::intmax_t i;
178# pragma omp for nowait schedule(static)
179 for(i = 0; i < iNumBlocksInGrid; ++i)
180# else
181# pragma omp for nowait schedule(static)
182 for(TIdx i = 0; i < numIterations; ++i)
183# endif
184 {
185 // Make another lambda to work around #1288
186 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
187 wrappedLoopBody(i);
188 }
189 }
190 };
191
192 //! Helper type to check if TKernel has member ompScheduleChunkSize
193 //!
194 //! Is void for those types, ill-formed otherwise.
195 //!
196 //! \tparam TKernel The kernel type.
197 template<typename TKernel>
198 using HasScheduleChunkSize = std::void_t<decltype(TKernel::ompScheduleChunkSize)>;
199
200 //! Helper executor of parallel OpenMP loop with the static schedule
201 //!
202 //! Specialization for kernels with ompScheduleChunkSize member.
203 //!
204 //! \tparam TKernel The kernel type.
205 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
206 template<typename TKernel, typename TSchedule>
207 struct ParallelForStaticImpl<TKernel, TSchedule, HasScheduleChunkSize<TKernel>>
208 {
209 //! Run parallel OpenMP loop
210 //!
211 //! \tparam TLoopBody The loop body functor type.
212 //! \tparam TIdx The index type.
213 //!
214 //! \param kernel The kernel instance reference
215 //! \param loopBody The loop body functor instance, takes iteration index as input.
216 //! \param numIterations The number of loop iterations.
217 template<typename TLoopBody, typename TIdx>
219 TKernel const& kernel,
220 TLoopBody&& loopBody,
221 TIdx const numIterations,
222 TSchedule const&)
223 {
224# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
225 // header.
226 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
227 std::intmax_t i;
228# pragma omp for nowait schedule(static, kernel.ompScheduleChunkSize)
229 for(i = 0; i < iNumBlocksInGrid; ++i)
230# else
231# pragma omp for nowait schedule(static, kernel.ompScheduleChunkSize)
232 for(TIdx i = 0; i < numIterations; ++i)
233# endif
234 {
235 // Make another lambda to work around #1288
236 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
237 wrappedLoopBody(i);
238 }
239 }
240 };
241
242 //! Executor of parallel OpenMP loop with the static schedule
243 //!
244 //! Specialization for kernels not specializing the OmpSchedule trait.
245 //! Falls back to ParallelForStaticImpl for further dispatch.
246 //!
247 //! \tparam TKernel The kernel type.
248 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
249 template<typename TKernel, typename TSchedule>
250 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::Static> : ParallelForStaticImpl<TKernel, TSchedule>
251 {
252 };
253
254 //! Executor of parallel OpenMP loop with the dynamic schedule
255 //!
256 //! Specialization for kernels specializing the OmpSchedule trait.
257 //!
258 //! \tparam TKernel The kernel type.
259 template<typename TKernel>
260 struct ParallelForImpl<TKernel, omp::Schedule, omp::Schedule::Dynamic>
261 {
262 //! Run parallel OpenMP loop
263 //!
264 //! \tparam TLoopBody The loop body functor type.
265 //! \tparam TIdx The index type.
266 //!
267 //! \param loopBody The loop body functor instance, takes iteration index as input.
268 //! \param numIterations The number of loop iterations.
269 //! \param schedule The schedule object.
270 template<typename TLoopBody, typename TIdx>
272 TKernel const&,
273 TLoopBody&& loopBody,
274 TIdx const numIterations,
275 omp::Schedule const& schedule)
276 {
277# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
278 // header.
279 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
280 std::intmax_t i;
281# pragma omp for nowait schedule(dynamic, schedule.chunkSize)
282 for(i = 0; i < iNumBlocksInGrid; ++i)
283# else
284# pragma omp for nowait schedule(dynamic, schedule.chunkSize)
285 for(TIdx i = 0; i < numIterations; ++i)
286# endif
287 {
288 // Make another lambda to work around #1288
289 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
290 wrappedLoopBody(i);
291 }
292 }
293 };
294
295 //! Helper executor of parallel OpenMP loop with the dynamic schedule
296 //!
297 //! Generel implementation is for TKernel types without member ompScheduleChunkSize.
298 //!
299 //! \tparam TKernel The kernel type.
300 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
301 template<typename TKernel, typename TSchedule, typename TSfinae = void>
303 {
304 //! Run parallel OpenMP loop
305 //!
306 //! \tparam TLoopBody The loop body functor type.
307 //! \tparam TIdx The index type.
308 //!
309 //! \param loopBody The loop body functor instance, takes iteration index as input.
310 //! \param numIterations The number of loop iterations.
311 template<typename TLoopBody, typename TIdx>
313 TKernel const&,
314 TLoopBody&& loopBody,
315 TIdx const numIterations,
316 TSchedule const&)
317 {
318# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
319 // header.
320 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
321 std::intmax_t i;
322# pragma omp for nowait schedule(dynamic)
323 for(i = 0; i < iNumBlocksInGrid; ++i)
324# else
325# pragma omp for nowait schedule(dynamic)
326 for(TIdx i = 0; i < numIterations; ++i)
327# endif
328 {
329 // Make another lambda to work around #1288
330 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
331 wrappedLoopBody(i);
332 }
333 }
334 };
335
336 //! Helper executor of parallel OpenMP loop with the dynamic schedule
337 //!
338 //! Specialization for kernels with ompScheduleChunkSize member.
339 //!
340 //! \tparam TKernel The kernel type.
341 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
342 template<typename TKernel, typename TSchedule>
343 struct ParallelForDynamicImpl<TKernel, TSchedule, HasScheduleChunkSize<TKernel>>
344 {
345 //! Run parallel OpenMP loop
346 //!
347 //! \tparam TLoopBody The loop body functor type.
348 //! \tparam TIdx The index type.
349 //!
350 //! \param kernel The kernel instance reference
351 //! \param loopBody The loop body functor instance, takes iteration index as input.
352 //! \param numIterations The number of loop iterations.
353 template<typename TLoopBody, typename TIdx>
355 TKernel const& kernel,
356 TLoopBody&& loopBody,
357 TIdx const numIterations,
358 TSchedule const&)
359 {
360# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
361 // header.
362 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
363 std::intmax_t i;
364# pragma omp for nowait schedule(dynamic, kernel.ompScheduleChunkSize)
365 for(i = 0; i < iNumBlocksInGrid; ++i)
366# else
367# pragma omp for nowait schedule(dynamic, kernel.ompScheduleChunkSize)
368 for(TIdx i = 0; i < numIterations; ++i)
369# endif
370 {
371 // Make another lambda to work around #1288
372 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
373 wrappedLoopBody(i);
374 }
375 }
376 };
377
378 //! Executor of parallel OpenMP loop with the dynamic schedule
379 //!
380 //! Specialization for kernels not specializing the OmpSchedule trait.
381 //! Falls back to ParallelForDynamicImpl for further dispatch.
382 //!
383 //! \tparam TKernel The kernel type.
384 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
385 template<typename TKernel, typename TSchedule>
386 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::Dynamic> : ParallelForDynamicImpl<TKernel, TSchedule>
387 {
388 };
389
390 //! Executor of parallel OpenMP loop with the guided schedule
391 //!
392 //! Specialization for kernels specializing the OmpSchedule trait.
393 //!
394 //! \tparam TKernel The kernel type.
395 template<typename TKernel>
396 struct ParallelForImpl<TKernel, omp::Schedule, omp::Schedule::Guided>
397 {
398 //! Run parallel OpenMP loop
399 //!
400 //! \tparam TLoopBody The loop body functor type.
401 //! \tparam TIdx The index type.
402 //!
403 //! \param loopBody The loop body functor instance, takes iteration index as input.
404 //! \param numIterations The number of loop iterations.
405 //! \param schedule The schedule object.
406 template<typename TLoopBody, typename TIdx>
408 TKernel const&,
409 TLoopBody&& loopBody,
410 TIdx const numIterations,
411 omp::Schedule const& schedule)
412 {
413# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
414 // header.
415 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
416 std::intmax_t i;
417# pragma omp for nowait schedule(guided, schedule.chunkSize)
418 for(i = 0; i < iNumBlocksInGrid; ++i)
419# else
420# pragma omp for nowait schedule(guided, schedule.chunkSize)
421 for(TIdx i = 0; i < numIterations; ++i)
422# endif
423 {
424 // Make another lambda to work around #1288
425 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
426 wrappedLoopBody(i);
427 }
428 }
429 };
430
431 //! Helper executor of parallel OpenMP loop with the guided schedule
432 //!
433 //! Generel implementation is for TKernel types without member ompScheduleChunkSize.
434 //!
435 //! \tparam TKernel The kernel type.
436 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
437 template<typename TKernel, typename TSchedule, typename TSfinae = void>
439 {
440 //! Run parallel OpenMP loop
441 //!
442 //! \tparam TLoopBody The loop body functor type.
443 //! \tparam TIdx The index type.
444 //!
445 //! \param loopBody The loop body functor instance, takes iteration index as input.
446 //! \param numIterations The number of loop iterations.
447 template<typename TLoopBody, typename TIdx>
449 TKernel const&,
450 TLoopBody&& loopBody,
451 TIdx const numIterations,
452 TSchedule const&)
453 {
454# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
455 // header.
456 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
457 std::intmax_t i;
458# pragma omp for nowait schedule(guided)
459 for(i = 0; i < iNumBlocksInGrid; ++i)
460# else
461# pragma omp for nowait schedule(guided)
462 for(TIdx i = 0; i < numIterations; ++i)
463# endif
464 {
465 // Make another lambda to work around #1288
466 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
467 wrappedLoopBody(i);
468 }
469 }
470 };
471
472 //! Helper executor of parallel OpenMP loop with the guided schedule
473 //!
474 //! Specialization for kernels with ompScheduleChunkSize member.
475 //!
476 //! \tparam TKernel The kernel type.
477 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
478 template<typename TKernel, typename TSchedule>
479 struct ParallelForGuidedImpl<TKernel, TSchedule, HasScheduleChunkSize<TKernel>>
480 {
481 //! Run parallel OpenMP loop
482 //!
483 //! \tparam TLoopBody The loop body functor type.
484 //! \tparam TIdx The index type.
485 //!
486 //! \param kernel The kernel instance reference
487 //! \param loopBody The loop body functor instance, takes iteration index as input.
488 //! \param numIterations The number of loop iterations.
489 template<typename TLoopBody, typename TIdx>
491 TKernel const& kernel,
492 TLoopBody&& loopBody,
493 TIdx const numIterations,
494 TSchedule const&)
495 {
496# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
497 // header.
498 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
499 std::intmax_t i;
500# pragma omp for nowait schedule(guided, kernel.ompScheduleChunkSize)
501 for(i = 0; i < iNumBlocksInGrid; ++i)
502# else
503# pragma omp for nowait schedule(guided, kernel.ompScheduleChunkSize)
504 for(TIdx i = 0; i < numIterations; ++i)
505# endif
506 {
507 // Make another lambda to work around #1288
508 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
509 wrappedLoopBody(i);
510 }
511 }
512 };
513
514 //! Executor of parallel OpenMP loop with the guided schedule
515 //!
516 //! Specialization for kernels not specializing the OmpSchedule trait.
517 //! Falls back to ParallelForGuidedImpl for further dispatch.
518 //!
519 //! \tparam TKernel The kernel type.
520 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
521 template<typename TKernel, typename TSchedule>
522 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::Guided> : ParallelForGuidedImpl<TKernel, TSchedule>
523 {
524 };
525
526# if _OPENMP >= 200805
527 //! Executor of parallel OpenMP loop with auto schedule set
528 //!
529 //! Does not use chunk size.
530 //!
531 //! \tparam TKernel The kernel type.
532 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
533 template<typename TKernel, typename TSchedule>
534 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::Auto>
535 {
536 //! Run parallel OpenMP loop
537 //!
538 //! \tparam TLoopBody The loop body functor type.
539 //! \tparam TIdx The index type.
540 //!
541 //! \param loopBody The loop body functor instance, takes iteration index as input.
542 //! \param numIterations The number of loop iterations.
543 template<typename TLoopBody, typename TIdx>
545 TKernel const&,
546 TLoopBody&& loopBody,
547 TIdx const numIterations,
548 TSchedule const&)
549 {
550# pragma omp for nowait schedule(auto)
551 for(TIdx i = 0; i < numIterations; ++i)
552 {
553 // Make another lambda to work around #1288
554 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
555 wrappedLoopBody(i);
556 }
557 }
558 };
559# endif
560
561 //! Executor of parallel OpenMP loop with runtime schedule set
562 //!
563 //! Does not use chunk size.
564 //!
565 //! \tparam TKernel The kernel type.
566 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
567 template<typename TKernel, typename TSchedule>
568 struct ParallelForImpl<TKernel, TSchedule, omp::Schedule::Runtime>
569 {
570 //! Run parallel OpenMP loop
571 //!
572 //! \tparam TLoopBody The loop body functor type.
573 //! \tparam TIdx The index type.
574 //!
575 //! \param loopBody The loop body functor instance, takes iteration index as input.
576 //! \param numIterations The number of loop iterations.
577 template<typename TLoopBody, typename TIdx>
579 TKernel const&,
580 TLoopBody&& loopBody,
581 TIdx const numIterations,
582 TSchedule const&)
583 {
584# if _OPENMP < 200805 // For OpenMP < 3.0 you have to declare the loop index (a signed integer) outside of the loop
585 // header.
586 std::intmax_t iNumBlocksInGrid(static_cast<std::intmax_t>(numIterations));
587 std::intmax_t i;
588# pragma omp for nowait schedule(runtime)
589 for(i = 0; i < iNumBlocksInGrid; ++i)
590# else
591# pragma omp for nowait schedule(runtime)
592 for(TIdx i = 0; i < numIterations; ++i)
593# endif
594 {
595 // Make another lambda to work around #1288
596 auto wrappedLoopBody = [&loopBody](auto idx) { loopBody(idx); };
597 wrappedLoopBody(i);
598 }
599 }
600 };
601
602 //! Executor of parallel OpenMP loop
603 //!
604 //! Performs dispatch based on schedule kind and forwards to the corresponding ParallelForImpl.
605 //! The default implementation is for the kernels that do not set schedule in any way, compile-time dispatch.
606 //!
607 //! \tparam TKernel The kernel type.
608 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
609 template<typename TKernel, typename TSchedule, typename TSfinae = void>
611 {
612 //! Run parallel OpenMP loop
613 //!
614 //! \tparam TLoopBody The loop body functor type.
615 //! \tparam TIdx The index type.
616 //!
617 //! \param kernel The kernel instance reference
618 //! \param loopBody The loop body functor instance, takes iteration index as input.
619 //! \param numIterations The number of loop iterations.
620 //! \param schedule The schedule object.
621 template<typename TLoopBody, typename TIdx>
623 TKernel const& kernel,
624 TLoopBody&& loopBody,
625 TIdx const numIterations,
626 TSchedule const& schedule)
627 {
628 // Forward to ParallelForImpl that performs dispatch by by chunk size
630 kernel,
631 std::forward<TLoopBody>(loopBody),
632 numIterations,
633 schedule);
634 }
635 };
636
637 //! Executor of parallel OpenMP loop
638 //!
639 //! Performs dispatch based on schedule kind and forwards to the corresponding ParallelForImpl.
640 //! Specialization for kernels specializing the OmpSchedule trait, run-time dispatch.
641 //!
642 //! \tparam TKernel The kernel type.
643 template<typename TKernel>
644 struct ParallelFor<TKernel, omp::Schedule>
645 {
646 //! Run parallel OpenMP loop
647 //!
648 //! \tparam TLoopBody The loop body functor type.
649 //! \tparam TIdx The index type.
650 //!
651 //! \param kernel The kernel instance reference
652 //! \param loopBody The loop body functor instance, takes iteration index as input.
653 //! \param numIterations The number of loop iterations.
654 //! \param schedule The schedule object.
655 template<typename TLoopBody, typename TIdx>
657 TKernel const& kernel,
658 TLoopBody&& loopBody,
659 TIdx const numIterations,
660 omp::Schedule const& schedule)
661 {
662 // Forward to ParallelForImpl that performs dispatch by by chunk size
663 switch(schedule.kind)
664 {
667 kernel,
668 std::forward<TLoopBody>(loopBody),
669 numIterations,
670 schedule);
671 break;
674 kernel,
675 std::forward<TLoopBody>(loopBody),
676 numIterations,
677 schedule);
678 break;
681 kernel,
682 std::forward<TLoopBody>(loopBody),
683 numIterations,
684 schedule);
685 break;
688 kernel,
689 std::forward<TLoopBody>(loopBody),
690 numIterations,
691 schedule);
692 break;
693# if _OPENMP >= 200805
696 kernel,
697 std::forward<TLoopBody>(loopBody),
698 numIterations,
699 schedule);
700 break;
701# endif
704 kernel,
705 std::forward<TLoopBody>(loopBody),
706 numIterations,
707 schedule);
708 break;
709 }
710 }
711 };
712
713 //! Helper type to check if TSchedule is a type originating from OmpSchedule trait definition
714 //!
715 //! \tparam TSchedule The schedule type.
716 template<typename TSchedule>
718 = std::integral_constant<bool, std::is_same<TSchedule, omp::Schedule>::value>;
719
720 //! Helper type to check if member ompScheduleKind of TKernel should be used
721 //!
722 //! For that it has to be present, and no OmpSchedule trait specialized.
723 //! Is void for those types, ill-formed otherwise.
724 //!
725 //! \tparam TKernel The kernel type.
726 //! \tparam TSchedule The schedule type.
727 template<typename TKernel, typename TSchedule>
728 using UseScheduleKind
729 = std::enable_if_t<sizeof(TKernel::ompScheduleKind) && !IsOmpScheduleTraitSpecialized<TSchedule>::value>;
730
731 //! Executor of parallel OpenMP loop
732 //!
733 //! Performs dispatch based on schedule kind and forwards to the corresponding ParallelForImpl.
734 //! Specialization for kernels with ompScheduleKind member, compile-time dispatch.
735 //!
736 //! \tparam TKernel The kernel type.
737 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
738 template<typename TKernel, typename TSchedule>
739 struct ParallelFor<TKernel, TSchedule, UseScheduleKind<TKernel, TSchedule>>
740 {
741 //! Run parallel OpenMP loop
742 //!
743 //! \tparam TLoopBody The loop body functor type.
744 //! \tparam TIdx The index type.
745 //!
746 //! \param kernel The kernel instance reference
747 //! \param loopBody The loop body functor instance, takes iteration index as input.
748 //! \param numIterations The number of loop iterations.
749 //! \param schedule The schedule object.
750 template<typename TLoopBody, typename TIdx>
752 TKernel const& kernel,
753 TLoopBody&& loopBody,
754 TIdx const numIterations,
755 TSchedule const& schedule)
756 {
757 // Forward to ParallelForImpl that performs dispatch by by chunk size
759 kernel,
760 std::forward<TLoopBody>(loopBody),
761 numIterations,
762 schedule);
763 }
764 };
765
766 //! Run parallel OpenMP loop
767 //!
768 //! \tparam TKernel The kernel type.
769 //! \tparam TLoopBody The loop body functor type.
770 //! \tparam TIdx The index type.
771 //! \tparam TSchedule The schedule type (not necessarily omp::Schedule).
772 //!
773 //! \param kernel The kernel instance reference,
774 //! not perfect=forwarded to shorten SFINAE internally.
775 //! \param loopBody The loop body functor instance, takes iteration index as input.
776 //! \param numIterations The number of loop iterations.
777 //! \param schedule The schedule object.
778 template<typename TKernel, typename TLoopBody, typename TIdx, typename TSchedule>
780 TKernel const& kernel,
781 TLoopBody&& loopBody,
782 TIdx const numIterations,
783 TSchedule const& schedule)
784 {
785 // Forward to ParallelFor that performs first a dispatch by schedule kind, and then by chunk size
786 ParallelFor<TKernel, TSchedule>{}(kernel, std::forward<TLoopBody>(loopBody), numIterations, schedule);
787 }
788
789 } // namespace detail
790
791 //! The CPU OpenMP 2.0 block accelerator execution task.
792 //!
793 //! \tparam TCooperative Whether the task executes a cooperative kernel, that can synchronise the whole grid.
794 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
795 class TaskKernelCpuOmp2Blocks final : public WorkDivMembers<TDim, TIdx>
796 {
797 public:
798 template<typename TWorkDiv>
799 ALPAKA_FN_HOST TaskKernelCpuOmp2Blocks(TWorkDiv&& workDiv, TKernelFnObj const& kernelFnObj, TArgs&&... args)
800 : WorkDivMembers<TDim, TIdx>(std::forward<TWorkDiv>(workDiv))
801 , m_kernelFnObj(kernelFnObj)
802 , m_args(std::forward<TArgs>(args)...)
803 {
804 static_assert(
805 Dim<std::decay_t<TWorkDiv>>::value == TDim::value,
806 "The work division and the execution task have to be of the same dimensionality!");
807 }
808
809 //! Executes the kernel function object.
810 ALPAKA_FN_HOST auto operator()() const -> void
811 {
813
814 auto const gridBlockExtent = getWorkDiv<Grid, Blocks>(*this);
815 auto const blockThreadExtent = getWorkDiv<Block, Threads>(*this);
816 auto const threadElemExtent = getWorkDiv<Thread, Elems>(*this);
817
818 // Get the size of the block shared dynamic memory.
819 auto const blockSharedMemDynSizeBytes = std::apply(
820 [&](std::decay_t<TArgs> const&... args)
821 {
823 m_kernelFnObj,
824 blockThreadExtent,
825 threadElemExtent,
826 args...);
827 },
828 m_args);
829
830# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
831 std::cout << __func__ << " blockSharedMemDynSizeBytes: " << blockSharedMemDynSizeBytes << " B"
832 << std::endl;
833# endif
834
835 // The number of blocks in the grid.
836 TIdx const numBlocksInGrid(gridBlockExtent.prod());
837
838 if constexpr(TCooperative)
839 {
840 cooperativeFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent);
841 }
842 else
843 {
844 // Get the OpenMP schedule information for the given kernel and parameter types
845 auto const schedule = std::apply(
846 [&](std::decay_t<TArgs> const&... args) {
848 m_kernelFnObj,
849 blockThreadExtent,
850 threadElemExtent,
851 args...);
852 },
853 m_args);
854
855 if(::omp_in_parallel() != 0)
856 {
857# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
858 std::cout << __func__ << " already within a parallel region." << std::endl;
859# endif
860 parallelFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent, schedule);
861 }
862 else
863 {
864# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
865 std::cout << __func__ << " opening new parallel region." << std::endl;
866# endif
867# pragma omp parallel
868 parallelFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent, schedule);
869 }
870 }
871 }
872
873 private:
874 template<typename TSchedule>
875 ALPAKA_FN_HOST auto parallelFn(
876 std::size_t const& blockSharedMemDynSizeBytes,
877 TIdx const& numBlocksInGrid,
878 Vec<TDim, TIdx> const& gridBlockExtent,
879 TSchedule const& schedule) const -> void
880 {
881# pragma omp single nowait
882 {
883 // The OpenMP runtime does not create a parallel region when either:
884 // * only one thread is required in the num_threads clause
885 // * or only one thread is available
886 // In all other cases we expect to be in a parallel region now.
887 if((numBlocksInGrid > 1) && (::omp_get_max_threads() > 1) && (::omp_in_parallel() == 0))
888 {
889 throw std::runtime_error("The OpenMP 2.0 runtime did not create a parallel region!");
890 }
891
892# if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
893 std::cout << __func__ << " omp_get_num_threads: " << ::omp_get_num_threads() << std::endl;
894# endif
895 }
896
897 AccCpuOmp2Blocks<TDim, TIdx> acc(
898 *static_cast<WorkDivMembers<TDim, TIdx> const*>(this),
899 blockSharedMemDynSizeBytes);
900
901 // Body of the OpenMP parallel loop to be executed.
902 // Index type is auto since we have a difference for OpenMP 2.0 and later ones
903 auto loopBody = [&](auto currentIndex)
904 {
905 runBlock(acc, static_cast<TIdx>(currentIndex), gridBlockExtent); // for issue #840
906 };
907
908 detail::parallelFor(m_kernelFnObj, loopBody, numBlocksInGrid, schedule);
909 }
910
911 //! Executes a cooperative kernel, where each OpenMP thread executes exactly one block.
912 //!
913 //! The grid synchronisation of cooperative kernels is an OpenMP barrier. OpenMP does not allow a barrier
914 //! inside a work-sharing construct like "omp for", and some implementations (e.g. MSVC) deadlock if it is.
915 //! So, cooperative kernels do not use "omp for": the block index is the OpenMP thread number, and the team
916 //! must have as many threads as there are blocks.
917 ALPAKA_FN_HOST auto cooperativeFn(
918 std::size_t const& blockSharedMemDynSizeBytes,
919 TIdx const& numBlocksInGrid,
920 Vec<TDim, TIdx> const& gridBlockExtent) const -> void
921 {
922 if(numBlocksInGrid == static_cast<TIdx>(0u))
923 {
924 return;
925 }
926
927 if(::omp_in_parallel() != 0)
928 {
929 // Every thread of the current team executes this task: use the current team as the grid.
930 int const numThreads = ::omp_get_num_threads();
931 if(static_cast<TIdx>(numThreads) != numBlocksInGrid)
932 {
933 throw std::runtime_error(
934 "A cooperative kernel with " + std::to_string(numBlocksInGrid)
935 + " blocks cannot run in an OpenMP parallel region with " + std::to_string(numThreads)
936 + " threads: the number of blocks and threads must be the same.");
937 }
938 cooperativeBlockFn(blockSharedMemDynSizeBytes, gridBlockExtent);
939 }
940 else
941 {
942 // The OpenMP runtime may create fewer threads than requested. In that case no thread executes a
943 // block, as the grid synchronisation would deadlock; the error is reported after the parallel region.
944 int teamSize = 0;
945# pragma omp parallel num_threads(static_cast<int>(numBlocksInGrid))
946 {
947 if(static_cast<TIdx>(::omp_get_num_threads()) == numBlocksInGrid)
948 {
949 cooperativeBlockFn(blockSharedMemDynSizeBytes, gridBlockExtent);
950 }
951# pragma omp master
952 teamSize = ::omp_get_num_threads();
953 }
954 if(static_cast<TIdx>(teamSize) != numBlocksInGrid)
955 {
956 throw std::runtime_error(
957 "The OpenMP runtime started " + std::to_string(teamSize) + " threads instead of "
958 + std::to_string(numBlocksInGrid) + " for a cooperative kernel.");
959 }
960 }
961 }
962
963 //! Executes the block with the index of the current OpenMP thread.
964 ALPAKA_FN_HOST auto cooperativeBlockFn(
965 std::size_t const& blockSharedMemDynSizeBytes,
966 Vec<TDim, TIdx> const& gridBlockExtent) const -> void
967 {
968 AccCpuOmp2Blocks<TDim, TIdx> acc(
969 *static_cast<WorkDivMembers<TDim, TIdx> const*>(this),
970 blockSharedMemDynSizeBytes);
971 runBlock(acc, static_cast<TIdx>(::omp_get_thread_num()), gridBlockExtent);
972 }
973
974 //! Executes the block with the given linear index.
975 ALPAKA_FN_HOST auto runBlock(
976 AccCpuOmp2Blocks<TDim, TIdx>& acc,
977 TIdx const& blockIdx,
978 Vec<TDim, TIdx> const& gridBlockExtent) const -> void
979 {
980 acc.m_gridBlockIdx = mapIdx<TDim::value>(Vec<DimInt<1u>, TIdx>(blockIdx), gridBlockExtent);
981
982 std::apply(
983 [&](auto&&... argsWithAcc)
984 { detail::checkKernelReturnType(m_kernelFnObj, std::forward<decltype(argsWithAcc)>(argsWithAcc)...); },
985 std::tuple_cat(std::tie(acc), m_args));
986 std::apply(m_kernelFnObj, std::tuple_cat(std::tie(acc), m_args));
987
988 // After a block has been processed, the shared memory has to be deleted.
989 freeSharedVars(acc);
990 }
991
992 TKernelFnObj m_kernelFnObj;
993 std::tuple<std::decay_t<TArgs>...> m_args;
994 };
995
996 namespace trait
997 {
998 //! The CPU OpenMP 2.0 grid block execution task accelerator type trait specialization.
999 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
1000 struct AccType<TaskKernelCpuOmp2Blocks<TDim, TIdx, TKernelFnObj, TCooperative, TArgs...>>
1001 {
1003 };
1004
1005 //! The CPU OpenMP 2.0 grid block execution task device type trait specialization.
1006 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
1007 struct DevType<TaskKernelCpuOmp2Blocks<TDim, TIdx, TKernelFnObj, TCooperative, TArgs...>>
1008 {
1009 using type = DevCpu;
1010 };
1011
1012 //! The CPU OpenMP 2.0 grid block execution task dimension getter trait specialization.
1013 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
1014 struct DimType<TaskKernelCpuOmp2Blocks<TDim, TIdx, TKernelFnObj, TCooperative, TArgs...>>
1015 {
1016 using type = TDim;
1017 };
1018
1019 //! The CPU OpenMP 2.0 grid block execution task platform type trait specialization.
1020 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
1021 struct PlatformType<TaskKernelCpuOmp2Blocks<TDim, TIdx, TKernelFnObj, TCooperative, TArgs...>>
1022 {
1024 };
1025
1026 //! The CPU OpenMP 2.0 block execution task idx type trait specialization.
1027 template<typename TDim, typename TIdx, typename TKernelFnObj, bool TCooperative, typename... TArgs>
1028 struct IdxType<TaskKernelCpuOmp2Blocks<TDim, TIdx, TKernelFnObj, TCooperative, TArgs...>>
1029 {
1030 using type = TIdx;
1031 };
1032
1033 //! \brief Specialisation of the class template FunctionAttributes
1034 //! \tparam TDev The device type.
1035 //! \tparam TDim The dimensionality of the accelerator device properties.
1036 //! \tparam TIdx The idx type of the accelerator device properties.
1037 //! \tparam TKernelFn Kernel function object type.
1038 //! \tparam TArgs Kernel function object argument types as a parameter pack.
1039 template<typename TDev, typename TDim, typename TIdx, typename TKernelFn, typename... TArgs>
1040 struct FunctionAttributes<AccCpuOmp2Blocks<TDim, TIdx>, TDev, TKernelFn, TArgs...>
1041 {
1042 //! \param dev The device instance
1043 //! \param kernelFn The kernel function object which should be executed.
1044 //! \param args The kernel invocation arguments.
1045 //! \return KernelFunctionAttributes instance. The default version always returns an instance with zero
1046 //! fields. For CPU, the field of max threads allowed by kernel function for the block is 1.
1048 TDev const& dev,
1049 [[maybe_unused]] TKernelFn const& kernelFn,
1050 [[maybe_unused]] TArgs&&... args) -> alpaka::KernelFunctionAttributes
1051 {
1052 alpaka::KernelFunctionAttributes kernelFunctionAttributes;
1053
1054 // set function properties for maxThreadsPerBlock to device properties, since API doesn't have function
1055 // properties function.
1057 kernelFunctionAttributes.maxThreadsPerBlock = static_cast<int>(props.m_blockThreadCountMax);
1058 kernelFunctionAttributes.maxDynamicSharedSizeBytes
1059 = static_cast<int>(alpaka::BlockSharedDynMemberAllocKiB * 1024);
1060 return kernelFunctionAttributes;
1061 }
1062 };
1063
1064 //! The CPU CPU OMP2 blocks get max active blocks for cooperative kernel specialization.
1065 template<typename TDev, typename TKernelFnObj, typename TDim, typename TIdx, typename... TArgs>
1066 struct MaxActiveBlocks<AccCpuOmp2Blocks<TDim, TIdx>, TDev, TKernelFnObj, TDim, TIdx, TArgs...>
1067 {
1069 TKernelFnObj const& /*kernelFnObj*/,
1070 TDev const& device,
1071 alpaka::Vec<TDim, TIdx> const& /*blockThreadExtent*/,
1072 alpaka::Vec<TDim, TIdx> const& /*threadElemExtent*/,
1073 TArgs const&... /*args*/) -> int
1074 {
1075 return static_cast<int>(
1077 }
1078 };
1079
1080 } // namespace trait
1081} // namespace alpaka
1082
1083# if ALPAKA_COMP_CLANG
1084# pragma clang diagnostic pop
1085# endif
1086
1087#endif
#define ALPAKA_DEBUG_MINIMAL_LOG_SCOPE
Definition Debug.hpp:55
The CPU OpenMP 2.0 block accelerator.
The CPU device handle.
Definition DevCpu.hpp:56
The CPU OpenMP 2.0 block accelerator execution task.
ALPAKA_FN_HOST auto operator()() const -> void
Executes the kernel function object.
ALPAKA_FN_HOST TaskKernelCpuOmp2Blocks(TWorkDiv &&workDiv, TKernelFnObj const &kernelFnObj, TArgs &&... args)
A n-dimensional vector.
Definition Vec.hpp:38
A basic class holding the work division as grid block extent, block thread and thread element extent.
ALPAKA_FN_HOST_ACC WorkDivMembers()=delete
#define ALPAKA_FN_HOST
Definition Common.hpp:43
#define ALPAKA_FN_INLINE
Macro defining the inline function attribute.
Definition Common.hpp:98
std::enable_if_t< sizeof(TKernel::ompScheduleKind) &&!IsOmpScheduleTraitSpecialized< TSchedule >::value > UseScheduleKind
Helper type to check if member ompScheduleKind of TKernel should be used.
std::void_t< decltype(TKernel::ompScheduleChunkSize)> HasScheduleChunkSize
Helper type to check if TKernel has member ompScheduleChunkSize.
ALPAKA_FN_HOST ALPAKA_FN_INLINE void parallelFor(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &schedule)
Run parallel OpenMP loop.
std::integral_constant< bool, std::is_same< TSchedule, omp::Schedule >::value > IsOmpScheduleTraitSpecialized
Helper type to check if TSchedule is a type originating from OmpSchedule trait definition.
ALPAKA_FN_HOST_ACC auto checkKernelReturnType(TKernelFnObj const &, TAcc const &, TArgs &&...) -> void
Definition Traits.hpp:372
The alpaka accelerator library.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getWorkDiv(TWorkDiv const &workDiv) -> Vec< Dim< TWorkDiv >, Idx< TWorkDiv > >
Get the extent requested.
Definition Traits.hpp:33
constexpr std::uint32_t BlockSharedDynMemberAllocKiB
ALPAKA_FN_HOST auto getAccDevProps(TDev const &dev) -> AccDevProps< Dim< TAcc >, Idx< TAcc > >
Definition Traits.hpp:95
Vec(TFirstIndex &&, TRestIndices &&...) -> Vec< DimInt< 1+sizeof...(TRestIndices)>, std::decay_t< TFirstIndex > >
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto mapIdx(Vec< DimInt< TDimIn >, TElem > const &in, Vec< DimInt< TDimExtents >, TElem > const &extent) -> Vec< DimInt< TDimOut >, TElem >
Maps an N-dimensional index to an N-dimensional position. At least one dimension must always be 1 or ...
Definition MapIdx.hpp:26
std::integral_constant< std::size_t, N > DimInt
ALPAKA_FN_HOST auto getOmpSchedule(TKernelFnObj const &kernelFnObj, Vec< TDim, Idx< TAcc > > const &blockThreadExtent, Vec< TDim, Idx< TAcc > > const &threadElemExtent, TArgs const &... args)
Definition Traits.hpp:319
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getBlockSharedMemDynSizeBytes(TKernelFnObj const &kernelFnObj, Vec< TDim, Idx< TAcc > > const &blockThreadExtent, Vec< TDim, Idx< TAcc > > const &threadElemExtent, TArgs const &... args) -> std::size_t
Definition Traits.hpp:197
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto freeSharedVars(TBlockSharedMemSt &blockSharedMemSt) -> void
Frees all memory used by block shared variables.
Definition Traits.hpp:54
typename trait::DimType< T >::type Dim
The dimension type trait alias template to remove the ::type.
Definition Traits.hpp:19
STL namespace.
Kernel function attributes struct. Attributes are filled by calling the API of the accelerator using ...
The CPU device platform.
ALPAKA_FN_HOST void operator()(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
Helper executor of parallel OpenMP loop with the dynamic schedule.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
Helper executor of parallel OpenMP loop with the guided schedule.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, omp::Schedule const &schedule)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, omp::Schedule const &schedule)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, omp::Schedule const &schedule)
Run parallel OpenMP loop.
Executor of parallel OpenMP loop with the given schedule.
ALPAKA_FN_HOST void operator()(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
Helper executor of parallel OpenMP loop with the static schedule.
ALPAKA_FN_HOST void operator()(TKernel const &, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &)
Run parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, omp::Schedule const &schedule)
Run parallel OpenMP loop.
Executor of parallel OpenMP loop.
ALPAKA_FN_HOST void operator()(TKernel const &kernel, TLoopBody &&loopBody, TIdx const numIterations, TSchedule const &schedule)
Run parallel OpenMP loop.
Representation of OpenMP schedule information: kind and chunk size. This class can be used regardless...
int chunkSize
Chunk size. Same as in OpenMP, value 0 corresponds to default chunk size. Using int and not a fixed-w...
Kind kind
Schedule kind.
The accelerator type trait.
Definition Traits.hpp:42
The device type trait.
Definition Traits.hpp:23
The dimension getter type trait.
Definition Traits.hpp:14
static ALPAKA_FN_HOST auto getFunctionAttributes(TDev const &dev, TKernelFn const &kernelFn, TArgs &&... args) -> alpaka::KernelFunctionAttributes
The structure template to access to the functions attributes of a kernel function object.
Definition Traits.hpp:94
The device properties get trait.
Definition Traits.hpp:66
The idx type trait.
Definition Traits.hpp:25
static ALPAKA_FN_HOST auto getMaxActiveBlocks(TKernelFnObj const &, TDev const &device, alpaka::Vec< TDim, TIdx > const &, alpaka::Vec< TDim, TIdx > const &, TArgs const &...) -> int
Get maximum requested blocks for cooperative kernel trait.
Definition Traits.hpp:50
The platform type trait.
Definition Traits.hpp:38