31#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
35#ifdef ALPAKA_ACC_CPU_B_OMP2_T_SEQ_ENABLED
38# pragma clang diagnostic push
39# pragma clang diagnostic ignored "-Wswitch-default"
43# error If ALPAKA_ACC_CPU_B_OMP2_T_SEQ_ENABLED is set, the compiler has to support OpenMP 2.0 or higher!
59 template<
typename TKernel,
typename TSchedule, omp::Schedule::Kind TScheduleKind>
68 template<
typename TKernel,
typename TSchedule>
78 template<
typename TLoopBody,
typename TIdx>
82 TIdx
const numIterations,
87 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
89# pragma omp for nowait
90 for(i = 0; i < iNumBlocksInGrid; ++i)
92# pragma omp
for nowait
93 for(TIdx i = 0; i < numIterations; ++i)
97 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
115 template<
typename TKernel>
126 template<
typename TLoopBody,
typename TIdx>
129 TLoopBody&& loopBody,
130 TIdx
const numIterations,
135 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
137# pragma omp for nowait schedule(static, schedule.chunkSize)
138 for(i = 0; i < iNumBlocksInGrid; ++i)
140# pragma omp
for nowait schedule(
static, schedule.
chunkSize)
141 for(TIdx i = 0; i < numIterations; ++i)
145 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
157 template<
typename TKernel,
typename TSchedule,
typename TSfinae =
void>
167 template<
typename TLoopBody,
typename TIdx>
170 TLoopBody&& loopBody,
171 TIdx
const numIterations,
176 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
178# pragma omp for nowait schedule(static)
179 for(i = 0; i < iNumBlocksInGrid; ++i)
181# pragma omp
for nowait schedule(
static)
182 for(TIdx i = 0; i < numIterations; ++i)
186 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
197 template<
typename TKernel>
206 template<
typename TKernel,
typename TSchedule>
217 template<
typename TLoopBody,
typename TIdx>
219 TKernel
const& kernel,
220 TLoopBody&& loopBody,
221 TIdx
const numIterations,
226 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
228# pragma omp for nowait schedule(static, kernel.ompScheduleChunkSize)
229 for(i = 0; i < iNumBlocksInGrid; ++i)
231# pragma omp
for nowait schedule(
static, kernel.ompScheduleChunkSize)
232 for(TIdx i = 0; i < numIterations; ++i)
236 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
249 template<
typename TKernel,
typename TSchedule>
259 template<
typename TKernel>
270 template<
typename TLoopBody,
typename TIdx>
273 TLoopBody&& loopBody,
274 TIdx
const numIterations,
279 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
281# pragma omp for nowait schedule(dynamic, schedule.chunkSize)
282 for(i = 0; i < iNumBlocksInGrid; ++i)
284# pragma omp
for nowait schedule(dynamic, schedule.
chunkSize)
285 for(TIdx i = 0; i < numIterations; ++i)
289 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
301 template<
typename TKernel,
typename TSchedule,
typename TSfinae =
void>
311 template<
typename TLoopBody,
typename TIdx>
314 TLoopBody&& loopBody,
315 TIdx
const numIterations,
320 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
322# pragma omp for nowait schedule(dynamic)
323 for(i = 0; i < iNumBlocksInGrid; ++i)
325# pragma omp
for nowait schedule(dynamic)
326 for(TIdx i = 0; i < numIterations; ++i)
330 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
342 template<
typename TKernel,
typename TSchedule>
353 template<
typename TLoopBody,
typename TIdx>
355 TKernel
const& kernel,
356 TLoopBody&& loopBody,
357 TIdx
const numIterations,
362 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
364# pragma omp for nowait schedule(dynamic, kernel.ompScheduleChunkSize)
365 for(i = 0; i < iNumBlocksInGrid; ++i)
367# pragma omp
for nowait schedule(dynamic, kernel.ompScheduleChunkSize)
368 for(TIdx i = 0; i < numIterations; ++i)
372 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
385 template<
typename TKernel,
typename TSchedule>
395 template<
typename TKernel>
406 template<
typename TLoopBody,
typename TIdx>
409 TLoopBody&& loopBody,
410 TIdx
const numIterations,
415 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
417# pragma omp for nowait schedule(guided, schedule.chunkSize)
418 for(i = 0; i < iNumBlocksInGrid; ++i)
420# pragma omp
for nowait schedule(guided, schedule.
chunkSize)
421 for(TIdx i = 0; i < numIterations; ++i)
425 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
437 template<
typename TKernel,
typename TSchedule,
typename TSfinae =
void>
447 template<
typename TLoopBody,
typename TIdx>
450 TLoopBody&& loopBody,
451 TIdx
const numIterations,
456 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
458# pragma omp for nowait schedule(guided)
459 for(i = 0; i < iNumBlocksInGrid; ++i)
461# pragma omp
for nowait schedule(guided)
462 for(TIdx i = 0; i < numIterations; ++i)
466 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
478 template<
typename TKernel,
typename TSchedule>
489 template<
typename TLoopBody,
typename TIdx>
491 TKernel
const& kernel,
492 TLoopBody&& loopBody,
493 TIdx
const numIterations,
498 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
500# pragma omp for nowait schedule(guided, kernel.ompScheduleChunkSize)
501 for(i = 0; i < iNumBlocksInGrid; ++i)
503# pragma omp
for nowait schedule(guided, kernel.ompScheduleChunkSize)
504 for(TIdx i = 0; i < numIterations; ++i)
508 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
521 template<
typename TKernel,
typename TSchedule>
526# if _OPENMP >= 200805
533 template<
typename TKernel,
typename TSchedule>
543 template<
typename TLoopBody,
typename TIdx>
546 TLoopBody&& loopBody,
547 TIdx
const numIterations,
550# pragma omp for nowait schedule(auto)
551 for(TIdx i = 0; i < numIterations; ++i)
554 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
567 template<
typename TKernel,
typename TSchedule>
577 template<
typename TLoopBody,
typename TIdx>
580 TLoopBody&& loopBody,
581 TIdx
const numIterations,
586 std::intmax_t iNumBlocksInGrid(
static_cast<std::intmax_t
>(numIterations));
588# pragma omp for nowait schedule(runtime)
589 for(i = 0; i < iNumBlocksInGrid; ++i)
591# pragma omp
for nowait schedule(runtime)
592 for(TIdx i = 0; i < numIterations; ++i)
596 auto wrappedLoopBody = [&loopBody](
auto idx) { loopBody(idx); };
609 template<
typename TKernel,
typename TSchedule,
typename TSfinae =
void>
621 template<
typename TLoopBody,
typename TIdx>
623 TKernel
const& kernel,
624 TLoopBody&& loopBody,
625 TIdx
const numIterations,
626 TSchedule
const& schedule)
631 std::forward<TLoopBody>(loopBody),
643 template<
typename TKernel>
655 template<
typename TLoopBody,
typename TIdx>
657 TKernel
const& kernel,
658 TLoopBody&& loopBody,
659 TIdx
const numIterations,
663 switch(schedule.
kind)
668 std::forward<TLoopBody>(loopBody),
675 std::forward<TLoopBody>(loopBody),
682 std::forward<TLoopBody>(loopBody),
689 std::forward<TLoopBody>(loopBody),
693# if _OPENMP >= 200805
697 std::forward<TLoopBody>(loopBody),
705 std::forward<TLoopBody>(loopBody),
716 template<
typename TSchedule>
718 = std::integral_constant<bool, std::is_same<TSchedule, omp::Schedule>::value>;
727 template<
typename TKernel,
typename TSchedule>
738 template<
typename TKernel,
typename TSchedule>
750 template<
typename TLoopBody,
typename TIdx>
752 TKernel
const& kernel,
753 TLoopBody&& loopBody,
754 TIdx
const numIterations,
755 TSchedule
const& schedule)
760 std::forward<TLoopBody>(loopBody),
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)
794 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
798 template<
typename TWorkDiv>
801 , m_kernelFnObj(kernelFnObj)
802 , m_args(
std::forward<TArgs>(args)...)
806 "The work division and the execution task have to be of the same dimensionality!");
819 auto const blockSharedMemDynSizeBytes = std::apply(
820 [&](std::decay_t<TArgs>
const&... args)
830# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
831 std::cout << __func__ <<
" blockSharedMemDynSizeBytes: " << blockSharedMemDynSizeBytes <<
" B"
836 TIdx
const numBlocksInGrid(gridBlockExtent.prod());
838 if constexpr(TCooperative)
840 cooperativeFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent);
845 auto const schedule = std::apply(
846 [&](std::decay_t<TArgs>
const&... args) {
855 if(::omp_in_parallel() != 0)
857# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
858 std::cout << __func__ <<
" already within a parallel region." << std::endl;
860 parallelFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent, schedule);
864# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
865 std::cout << __func__ <<
" opening new parallel region." << std::endl;
868 parallelFn(blockSharedMemDynSizeBytes, numBlocksInGrid, gridBlockExtent, schedule);
874 template<
typename TSchedule>
876 std::size_t
const& blockSharedMemDynSizeBytes,
877 TIdx
const& numBlocksInGrid,
879 TSchedule
const& schedule)
const ->
void
881# pragma omp single nowait
887 if((numBlocksInGrid > 1) && (::omp_get_max_threads() > 1) && (::omp_in_parallel() == 0))
889 throw std::runtime_error(
"The OpenMP 2.0 runtime did not create a parallel region!");
892# if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
893 std::cout << __func__ <<
" omp_get_num_threads: " << ::omp_get_num_threads() << std::endl;
897 AccCpuOmp2Blocks<TDim, TIdx> acc(
899 blockSharedMemDynSizeBytes);
903 auto loopBody = [&](
auto currentIndex)
905 runBlock(acc,
static_cast<TIdx
>(currentIndex), gridBlockExtent);
918 std::size_t
const& blockSharedMemDynSizeBytes,
919 TIdx
const& numBlocksInGrid,
920 Vec<TDim, TIdx>
const& gridBlockExtent)
const ->
void
922 if(numBlocksInGrid ==
static_cast<TIdx
>(0u))
927 if(::omp_in_parallel() != 0)
930 int const numThreads = ::omp_get_num_threads();
931 if(
static_cast<TIdx
>(numThreads) != numBlocksInGrid)
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.");
938 cooperativeBlockFn(blockSharedMemDynSizeBytes, gridBlockExtent);
945# pragma omp parallel num_threads(static_cast<int>(numBlocksInGrid))
947 if(
static_cast<TIdx
>(::omp_get_num_threads()) == numBlocksInGrid)
949 cooperativeBlockFn(blockSharedMemDynSizeBytes, gridBlockExtent);
952 teamSize = ::omp_get_num_threads();
954 if(
static_cast<TIdx
>(teamSize) != numBlocksInGrid)
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.");
965 std::size_t
const& blockSharedMemDynSizeBytes,
966 Vec<TDim, TIdx>
const& gridBlockExtent)
const ->
void
968 AccCpuOmp2Blocks<TDim, TIdx> acc(
970 blockSharedMemDynSizeBytes);
971 runBlock(acc,
static_cast<TIdx
>(::omp_get_thread_num()), gridBlockExtent);
976 AccCpuOmp2Blocks<TDim, TIdx>& acc,
977 TIdx
const& blockIdx,
978 Vec<TDim, TIdx>
const& gridBlockExtent)
const ->
void
983 [&](
auto&&... argsWithAcc)
985 std::tuple_cat(std::tie(acc), m_args));
986 std::apply(m_kernelFnObj, std::tuple_cat(std::tie(acc), m_args));
992 TKernelFnObj m_kernelFnObj;
993 std::tuple<std::decay_t<TArgs>...> m_args;
999 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
1006 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
1013 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
1020 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
1027 template<
typename TDim,
typename TIdx,
typename TKernelFnObj,
bool TCooperative,
typename... TArgs>
1039 template<
typename TDev,
typename TDim,
typename TIdx,
typename TKernelFn,
typename... TArgs>
1049 [[maybe_unused]] TKernelFn
const& kernelFn,
1057 kernelFunctionAttributes.
maxThreadsPerBlock =
static_cast<int>(props.m_blockThreadCountMax);
1060 return kernelFunctionAttributes;
1065 template<
typename TDev,
typename TKernelFnObj,
typename TDim,
typename TIdx,
typename... TArgs>
1069 TKernelFnObj
const& ,
1073 TArgs
const&... ) ->
int
1075 return static_cast<int>(
1083# if ALPAKA_COMP_CLANG
1084# pragma clang diagnostic pop
#define ALPAKA_DEBUG_MINIMAL_LOG_SCOPE
The CPU OpenMP 2.0 block accelerator.
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 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_INLINE
Macro defining the inline function attribute.
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
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.
constexpr std::uint32_t BlockSharedDynMemberAllocKiB
ALPAKA_FN_HOST auto getAccDevProps(TDev const &dev) -> AccDevProps< Dim< TAcc >, Idx< TAcc > >
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 ...
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)
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
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto freeSharedVars(TBlockSharedMemSt &blockSharedMemSt) -> void
Frees all memory used by block shared variables.
typename trait::DimType< T >::type Dim
The dimension type trait alias template to remove the ::type.
Kernel function attributes struct. Attributes are filled by calling the API of the accelerator using ...
int maxDynamicSharedSizeBytes
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...
The accelerator type trait.
The dimension getter type trait.
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.
The device properties get trait.
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.