12#ifndef ARCANE_ACCELERATOR_WORKGROUPLOOPRANGE_H
13#define ARCANE_ACCELERATOR_WORKGROUPLOOPRANGE_H
17#include "arcane/accelerator/AcceleratorUtils.h"
19#if defined(ARCANE_COMPILING_CUDA)
20#include <cooperative_groups.h>
22#if defined(ARCANE_COMPILING_HIP)
23#include <hip/hip_cooperative_groups.h>
39class SyclDeviceWorkItemBlock;
40class DeviceWorkItemBlock;
41class SyclWorkGroupLoopContext;
50 friend WorkGroupLoopContext;
51 friend SyclDeviceWorkItemBlock;
52 friend DeviceWorkItemBlock;
53 friend HostWorkItemGroup;
59 : m_loop_index(loop_index)
69 Int32 m_loop_index = 0;
88 friend WorkGroupLoopContext;
89 friend SyclDeviceWorkItemBlock;
90 friend DeviceWorkItemBlock;
96 : m_loop_index(loop_index)
97 , m_group_size(group_size)
98 , m_group_index(group_index)
99 , m_nb_active_item(nb_active_item)
125 ARCANE_CHECK_AT(index, m_nb_active_item);
131 Int32 m_loop_index = 0;
132 Int32 m_group_size = 0;
133 Int32 m_group_index = 0;
134 Int32 m_nb_active_item = 0;
140#if defined(ARCANE_COMPILING_CUDA) || defined(ARCANE_COMPILING_HIP)
147class DeviceWorkItemBlock
159 explicit __device__ DeviceWorkItemBlock()
160 : m_thread_block(cooperative_groups::this_thread_block())
166 __device__ Int32 groupRank()
const {
return m_thread_block.group_index().x; }
169 __device__ Int32 groupSize() {
return m_thread_block.group_dim().x; }
172 __device__ Int32 activeWorkItemRankInGroup()
const {
return m_thread_block.thread_index().x; }
175 __device__
void barrier() { m_thread_block.sync(); }
178 static constexpr __device__
bool isDevice() {
return true; }
181 constexpr __device__ Int32 nbActiveItem()
const {
return 1; }
184 __device__ WorkItem activeItem(Int32 index)
187 ARCANE_CHECK_AT(index, 1);
188 return WorkItem(blockDim.x * blockIdx.x + threadIdx.x);
193 cooperative_groups::thread_block m_thread_block;
210 friend WorkGroupLoopRange;
217 : m_loop_index(loop_index)
218 , m_group_index(group_index)
219 , m_group_size(group_size)
220 , m_nb_active_item(nb_active_item)
230#if defined(ARCCORE_DEVICE_CODE) && !defined(ARCANE_COMPILING_SYCL)
232 __device__ DeviceWorkItemBlock
group()
const {
return DeviceWorkItemBlock(); }
240 Int32 m_loop_index = 0;
241 Int32 m_group_index = 0;
242 Int32 m_group_size = 0;
243 Int32 m_nb_active_item = 0;
268#if defined(ARCANE_COMPILING_SYCL)
273class SyclDeviceWorkItemBlock
275 friend SyclWorkGroupLoopContext;
279 explicit SyclDeviceWorkItemBlock(sycl::nd_item<1> n)
287 Int32 groupRank()
const {
return static_cast<Int32
>(m_nd_item.get_group(0)); }
290 Int32 groupSize() {
return static_cast<Int32
>(m_nd_item.get_local_range(0)); }
293 Int32 activeWorkItemRankInGroup()
const {
return static_cast<Int32
>(m_nd_item.get_local_id(0)); }
296 void barrier() { m_nd_item.barrier(); }
299 static constexpr bool isDevice() {
return true; }
302 constexpr Int32 nbActiveItem()
const {
return 1; }
305 WorkItem activeItem(Int32 index)
308 ARCANE_CHECK_AT(index, 1);
309 return WorkItem(
static_cast<Int32
>(m_nd_item.get_group(0) * m_nd_item.get_local_range(0) + m_nd_item.get_local_id(0)));
314 sycl::nd_item<1> m_nd_item;
324class SyclWorkGroupLoopContext
326 friend WorkGroupLoopRange;
331 explicit SyclWorkGroupLoopContext(sycl::nd_item<1> n)
339 SyclDeviceWorkItemBlock group()
const {
return SyclDeviceWorkItemBlock(m_nd_item); }
343 sycl::nd_item<1> m_nd_item;
364class ARCANE_ACCELERATOR_EXPORT WorkGroupLoopRange
368 friend ARCANE_ACCELERATOR_EXPORT WorkGroupLoopRange
370 friend ARCANE_ACCELERATOR_EXPORT WorkGroupLoopRange
379 WorkGroupLoopRange() =
default;
389 WorkGroupLoopRange(
Int32 total_nb_element,
Int32 nb_group,
Int32 group_size);
404 return ((i + 1) != m_nb_group) ? m_group_size : m_last_group_size;
410#if defined(ARCANE_COMPILING_CUDA) || defined(ARCANE_COMPILING_HIP)
414#if defined(ARCANE_COMPILING_SYCL)
416 SyclWorkGroupLoopContext getIndices(sycl::nd_item<1>
id)
const
418 return SyclWorkGroupLoopContext(
id);
424 Int32 m_total_size = 0;
425 Int32 m_nb_group = 0;
426 Int32 m_group_size = 0;
427 Int32 m_last_group_size = 0;
Gère un groupe de WorkItem dans un WorkGroupLoopRange pour l'hôte.
constexpr __host__ __device__ HostWorkItemGroup(Int32 loop_index, Int32 group_index, Int32 group_size, Int32 nb_active_item)
Constructeur pour l'hôte.
WorkItem activeItem(Int32 index) const
Récupère le index-ème WorkItem à gérer.
static constexpr bool isDevice()
Indique si on s'exécute sur un accélérateur.
void barrier()
Bloque tant que tous les WorkItem du groupe ne sont pas arrivés ici.
constexpr Int32 activeWorkItemRankInGroup() const
Rang du WorkItem actif dans son WorkGroup.
constexpr Int32 groupRank() const
Rang du groupe du WorkItem dans la liste des WorkGroup.
constexpr Int32 nbActiveItem() const
Nombre de WorkItem à gérer dans l'itération.
constexpr Int32 groupSize() const
Nombre de WorkItem dans un WorkGroup.
Classe pour exécuter en séquentiel sur l'hôte une partie de la boucle.
Gestion d'une commande sur accélérateur.
Contexte d'exécution d'une commande sur un ensemble de blocs.
HostWorkItemGroup group() const
Groupe courant.
constexpr WorkGroupLoopContext(Int32 loop_index, Int32 group_index, Int32 group_size, Int32 nb_active_item)
Ce constructeur est utilisé dans l'implémentation hôte.
Intervalle d'itération d'une boucle utilisant le parallélisme hiérarchique.
constexpr Int32 nbActiveItem(Int32 i) const
Nombre d'éléments actifs pour le i-ème groupe.
constexpr Int32 nbGroup() const
Nombre de groupes.
constexpr Int32 lastGroupSize() const
Nombre d'éléments du dernier groupe.
constexpr Int32 nbElement() const
Nombre d'éléments à traiter.
friend WorkGroupLoopRange makeWorkGroupLoopRange(RunCommand &command, Int32 nb_group, Int32 group_size)
Créé un intervalle d'itération pour la commande command.
friend WorkGroupLoopRange makeWorkGroupLoopRange(RunCommand &command, Int32 nb_element, Int32 nb_group, Int32 group_size)
Créé un intervalle d'itération pour la commande command.
constexpr Int32 groupSize() const
Taille d'un groupe.
Représente un WorkItem dans le parallélisme hiérarchique.
constexpr __host__ __device__ WorkItem(Int32 loop_index)
Constructeur pour l'hôte.
constexpr Int32 linearIndex() const
Index linéaire entre 0 et WorkGroupLoopRange::nbElement()
Espace de nom pour l'utilisation des accélérateurs.
std::int32_t Int32
Type entier signé sur 32 bits.