12#ifndef ARCANE_ACCELERATOR_REDUCE_H
13#define ARCANE_ACCELERATOR_REDUCE_H
17#include "arcane/utils/ArrayView.h"
18#include "arcane/utils/String.h"
20#include "arcane/accelerator/core/IReduceMemoryImpl.h"
21#include "arcane/accelerator/AcceleratorGlobal.h"
22#include "arcane/accelerator/CommonUtils.h"
23#include "arcane/accelerator/RunCommandLaunchInfo.h"
36class HostReducerHelper;
39namespace Arcane::Accelerator::impl
41class KernelReducerHelper;
51extern "C++" ARCANE_ACCELERATOR_CORE_EXPORT IReduceMemoryImpl*
52internalGetOrCreateReduceMemoryImpl(RunCommand* command);
54template <
typename DataType>
62 ARCCORE_HOST_DEVICE
static constexpr double sumValue() {
return 0.0; }
63 ARCCORE_HOST_DEVICE
static constexpr double minValue() {
return DBL_MAX; }
64 ARCCORE_HOST_DEVICE
static constexpr double maxValue() {
return -
DBL_MAX; }
71 ARCCORE_HOST_DEVICE
static constexpr Int32 sumValue() {
return 0; }
72 ARCCORE_HOST_DEVICE
static constexpr Int32 minValue() {
return INT32_MAX; }
73 ARCCORE_HOST_DEVICE
static constexpr Int32 maxValue() {
return -INT32_MAX; }
80 ARCCORE_HOST_DEVICE
static constexpr Int64 sumValue() {
return 0; }
81 ARCCORE_HOST_DEVICE
static constexpr Int64 minValue() {
return INT64_MAX; }
82 ARCCORE_HOST_DEVICE
static constexpr Int64 maxValue() {
return -INT64_MAX; }
95template <
typename DataType>
123template <
typename DataType>
131 static double apply(
double*
vptr,
double v)
133 std::atomic_ref<double>
aref(*
vptr);
134 double old =
aref.load(std::memory_order_consume);
136 while (!
aref.compare_exchange_weak(
old,
wanted, std::memory_order_release, std::memory_order_consume))
169template <
typename DataType>
174 static ARCCORE_DEVICE DataType
178 return *(
dev_info.m_device_final_ptr);
180 static DataType apply(DataType*
vptr, DataType v)
184#if defined(ARCANE_COMPILING_SYCL)
185 static sycl::plus<DataType>
syclFunctor() {
return {}; }
200template <
typename DataType>
205 static ARCCORE_DEVICE DataType
209 return *(
dev_info.m_device_final_ptr);
211 static DataType apply(DataType*
ptr, DataType v)
213 std::atomic_ref<DataType>
aref(*
ptr);
219#if defined(ARCANE_COMPILING_SYCL)
220 static sycl::maximum<DataType>
syclFunctor() {
return {}; }
235template <
typename DataType>
240 static ARCCORE_DEVICE DataType
244 return *(
dev_info.m_device_final_ptr);
246 static DataType apply(DataType*
vptr, DataType v)
248 std::atomic_ref<DataType>
aref(*
vptr);
254#if defined(ARCANE_COMPILING_SYCL)
255 static sycl::minimum<DataType>
syclFunctor() {
return {}; }
301template <
typename DataType,
typename ReduceFunctor>
308 , m_command(&command)
311 m_is_master_instance =
true;
312 m_identity = ReduceFunctor::identity();
313 m_local_value = m_identity;
314 m_atomic_value = m_identity;
315 m_atomic_parent_value = &m_atomic_value;
317 m_memory_impl = impl::internalGetOrCreateReduceMemoryImpl(&command);
324#if defined(__INTEL_LLVM_COMPILER) && defined(__SYCL_DEVICE_ONLY__)
329 , m_local_value(
rhs.m_local_value)
330 , m_identity(
rhs.m_identity)
332#ifdef ARCCORE_DEVICE_CODE
333 m_grid_memory_info =
rhs.m_grid_memory_info;
338 m_memory_impl =
rhs.m_memory_impl;
343 m_atomic_parent_value =
rhs.m_atomic_parent_value;
344 m_local_value =
rhs.m_identity;
345 m_atomic_value = m_identity;
359 ARCCORE_HOST_DEVICE
void setValue(DataType v)
363 ARCCORE_HOST_DEVICE DataType localValue()
const
365 return m_local_value;
386 mutable DataType m_local_value;
387 DataType* m_atomic_parent_value =
nullptr;
388 mutable DataType m_atomic_value;
394 bool m_is_master_instance =
false;
401 if (!m_is_master_instance)
402 ARCANE_FATAL(
"Final reduce operation is only valid on master instance");
409 m_memory_impl =
nullptr;
412 if (m_atomic_parent_value) {
416 ReduceFunctor::apply(m_atomic_parent_value, *
final_ptr);
429 ARCCORE_HOST_DEVICE
void
432#ifdef ARCCORE_DEVICE_CODE
437 DataType* buf =
reinterpret_cast<DataType*
>(
buf_span.data());
445 dvi.m_current_value = m_local_value;
446 dvi.m_identity = m_identity;
448 ReduceFunctor::applyDevice(
dvi);
456 if (!m_is_master_instance)
457 ReduceFunctor::apply(m_atomic_parent_value, m_local_value);
472template <
typename DataType,
typename ReduceFunctor>
498 DataType reducedValue()
509template <
typename DataType,
typename ReduceFunctor>
514 friend ::Arcane::impl::HostReducerHelper;
519 using BaseClass::m_grid_memory_info;
521 using BaseClass::m_local_value;
531 DataType reducedValue()
541 void _internalReduceHost()
546#if defined(ARCANE_COMPILING_CUDA) || defined(ARCANE_COMPILING_HIP)
547 ARCCORE_HOST_DEVICE
void _internalExecWorkItem(
Int32)
553#if defined(ARCANE_COMPILING_SYCL)
554 void _internalExecWorkItem(sycl::nd_item<1>
id)
557 const Int32 local_id =
static_cast<Int32>(
id.get_local_id(0));
558 const Int32 group_id =
static_cast<Int32>(
id.get_group_linear_id());
559 const Int32 nb_block =
static_cast<Int32>(
id.get_group_range(0));
562 DataType* buf =
reinterpret_cast<DataType*
>(buf_span.data());
565 DataType v = m_local_value;
566 bool is_last =
false;
567 auto sycl_functor = ReduceFunctor::syclFunctor();
568 DataType local_sum = sycl::reduce_over_group(
id.get_group(), v, sycl_functor);
570 grid_buffer[group_id] = local_sum;
579#if defined(__ADAPTIVECPP__)
580 int* atomic_counter_ptr_as_int =
reinterpret_cast<int*
>(atomic_counter_ptr);
581 sycl::atomic_ref<int, sycl::memory_order::relaxed, sycl::memory_scope::device> a(*atomic_counter_ptr_as_int);
583 sycl::atomic_ref<unsigned int, sycl::memory_order::relaxed, sycl::memory_scope::device> a(*atomic_counter_ptr);
585 Int32 cx = a.fetch_add(1);
586 if (cx == (nb_block - 1))
593 DataType my_total = grid_buffer[0];
594 for (
int x = 1; x < nb_block; ++x)
595 my_total = sycl_functor(my_total, grid_buffer[x]);
597 grid_buffer[0] = my_total;
599 *atomic_counter_ptr = 0;
613template <
typename DataType,
typename ReduceFunctor>
624 return m_local_value;
626 void setValue(DataType v) { m_local_value = v; }
630 mutable DataType m_local_value = {};
636#if defined(ARCANE_COMPILING_SYCL)
650template <
typename DataType>
652:
public Reducer<DataType, impl::ReduceFunctorSum<DataType>>
655 using BaseClass::m_local_value;
665 ARCCORE_HOST_DEVICE DataType combine(DataType v)
const
668 return m_local_value;
671 ARCCORE_HOST_DEVICE DataType add(DataType v)
const
682template <
typename DataType>
684:
public Reducer<DataType, impl::ReduceFunctorMax<DataType>>
687 using BaseClass::m_local_value;
697 ARCCORE_HOST_DEVICE DataType combine(DataType v)
const
699 m_local_value = v > m_local_value ? v : m_local_value;
700 return m_local_value;
703 ARCCORE_HOST_DEVICE DataType max(DataType v)
const
717template <
typename DataType>
719:
public Reducer<DataType, impl::ReduceFunctorMin<DataType>>
722 using BaseClass::m_local_value;
732 ARCCORE_HOST_DEVICE DataType combine(DataType v)
const
734 m_local_value = v < m_local_value ? v : m_local_value;
735 return m_local_value;
738 ARCCORE_HOST_DEVICE DataType min(DataType v)
const
752template <
typename DataType>
766 ARCCORE_HOST_DEVICE
void combine(DataType v)
768 this->m_local_value += v;
777template <
typename DataType>
791 ARCCORE_HOST_DEVICE
void combine(DataType v)
793 DataType&
lv = this->m_local_value;
803template <
typename DataType>
817 ARCCORE_HOST_DEVICE
void combine(DataType v)
819 DataType&
lv = this->m_local_value;
836#define ARCANE_INLINE_REDUCE_IMPL
838#ifdef ARCANE_INLINE_REDUCE_IMPL
840# ifndef ARCANE_INLINE_REDUCE
841# define ARCANE_INLINE_REDUCE inline
844#if defined(__CUDACC__) || defined(__HIP__)
845# include "arcane/accelerator/CommonCudaHipReduceImpl.h"
855#include "arcane/utils/NumArray.h"
856#include "arcane/utils/FatalErrorException.h"
857#include "arcane/accelerator/core/RunQueue.h"
862namespace Arcane::Accelerator::impl
864template <
typename DataType>
865class GenericReducerIf;
871template <
typename DataType,
typename Operator>
874template <
typename DataType>
881template <
typename DataType>
888template <
typename DataType>
904template <
typename DataType>
917 DataType _reducedValue()
const
920 return m_host_reduce_storage[0];
926 if (m_host_reduce_storage.memoryRessource() !=
r)
928 m_host_reduce_storage.resize(1);
949template <
typename DataType>
957 template <
typename InputIterator,
typename ReduceOperator>
968#if defined(ARCANE_COMPILING_CUDA)
971 cudaStream_t stream = impl::CudaUtils::toNativeStream(queue);
979 ARCANE_CHECK_CUDA(::cub::DeviceReduce::Reduce(s.m_algo_storage.address(),
temp_storage_size,
982 s.m_device_reduce_storage.copyToAsync(s.m_host_reduce_storage, queue);
985#if defined(ARCANE_COMPILING_HIP)
988 hipStream_t stream = impl::HipUtils::toNativeStream(queue);
999 s.m_device_reduce_storage.copyToAsync(s.m_host_reduce_storage, queue);
1002#if defined(ARCANE_COMPILING_SYCL)
1014 s.m_host_reduce_storage[0] =
reducer.reducedValue();
1083template <
typename DataType>
1116 template <
typename SelectLambda>
1123 template <
typename SelectLambda>
1130 template <
typename SelectLambda>
1139 m_is_already_called =
false;
1140 return this->_reducedValue();
1145 bool m_is_already_called =
false;
1149 template <
typename InputIterator,
typename ReduceOperator>
1159 template <
typename GetterLambda,
typename ReduceOperator>
1164 impl::GenericReducerBase<DataType>*
base_ptr =
this;
1165 impl::GenericReducerIf<DataType>
gf;
1173 if (m_is_already_called)
1174 ARCANE_FATAL(
"apply() has already been called for this instance");
1175 m_is_already_called =
true;
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour gérer les boucles sur les accélérateurs.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
Algorithme générique de réduction sur accélérateur.
DataType reducedValue()
Valeur de la réduction.
void applyMinWithIndex(Int32 nb_value, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Min' sur les valeurs sélectionnées par select_lambda.
void applyMaxWithIndex(Int32 nb_value, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Max' sur les valeurs sélectionnées par select_lambda.
void applyMax(SmallSpan< const DataType > values, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Max' sur les valeurs values.
void applyMin(SmallSpan< const DataType > values, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Min' sur les valeurs values.
void applySum(SmallSpan< const DataType > values, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Somme' sur les valeurs values.
void applySumWithIndex(Int32 nb_value, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique une réduction 'Somme' sur les valeurs sélectionnées par select_lambda.
Version 2 de la réduction.
DataType * m_host_or_device_memory_for_reduced_value
Pointeur vers la donnée qui contiendra la valeur réduite.
DataType * m_host_or_device_memory_for_reduced_value
Pointeur vers la donnée qui contiendra la valeur réduite.
DataType _reduce()
Effectue la réduction et récupère la valeur. ATTENTION: ne faire qu'une seule fois.
Version 1 de la réduction.
Classe pour effectuer une réduction 'max'.
Classe pour effectuer une réduction 'max'.
Classe pour effectuer une réduction 'min'.
Classe pour effectuer une réduction 'min'.
Classe pour effectuer une réduction 'somme'.
Classe pour effectuer une réduction 'somme'.
Gestion d'une commande sur accélérateur.
File d'exécution pour un accélérateur.
void barrier() const
Bloque tant que toutes les commandes associées à la file ne sont pas terminées.
eExecutionPolicy executionPolicy() const
Politique d'exécution de la file.
Implémentation de la réduction pour le backend SYCL.
Gère l'allocation interne sur le device.
Classe de base pour effectuer une réduction.
Classe pour effectuer un partitionnement d'une liste.
Interface de la gestion mémoire pour les réductions.
virtual GridMemoryInfo gridMemoryInfo()=0
Informations sur la mémoire utilisée par la réduction.
virtual void copyReduceValueFromDevice()=0
Copie la valeur réduite depuis le device vers l'hote.
virtual void release()=0
Libère l'instance.
Classe pour appliquer la finalisation des réductions.
Opérateur de Scan/Reduce pour le maximum.
Opérateur de Scan/Reduce pour le minimum.
Informations pour effectuer une réduction sur un device.
DataType * m_device_final_ptr
Pointeur vers la donnée réduite (mémoire uniquement accessible depuis le device)
unsigned int * m_device_count
bool m_use_grid_reduce
Indique si on utilise la réduction par grille (sinon on utilise les atomiques)
void * m_host_final_ptr
Pointeur vers la donnée réduite (mémoire uniquement accessible depuis l'hôte)
DataType m_current_value
Valeur du thread courant à réduire.
SmallSpan< DataType > m_grid_buffer
Tableau avec une valeur par bloc pour la réduction.
DataType m_identity
Valeur de l'identité pour la réduction.
Object temporaire pour conserver les informations d'exécution d'une commande et regrouper les tests.
Opérateur de Scan/Reduce pour les sommes.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Vue d'un tableau d'éléments de type T.
Espace de nom pour l'utilisation des accélérateurs.
RunCommand makeCommand(const RunQueue &run_queue)
Créé une commande associée à la file run_queue.
@ Atomic
Utilise des opérations atomiques entre les blocs.
eExecutionPolicy
Politique d'exécution pour un Runner.
@ SYCL
Politique d'exécution utilisant l'environnement SYCL.
@ HIP
Politique d'exécution utilisant l'environnement HIP.
@ CUDA
Politique d'exécution utilisant l'environnement CUDA.
@ Sequential
Politique d'exécution séquentielle.
@ Thread
Politique d'exécution multi-thread.
eMemoryRessource
Liste des ressources mémoire disponibles.
@ HostPinned
Alloue sur l'hôte.
Espace de nom de Arccore.
std::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.
Informations mémoire pour la réduction sur les accélérateurs.
void * m_host_memory_for_reduced_value
Pointeur vers la mémoire sur l'hôte contenant la valeur réduite.
eDeviceReducePolicy m_reduce_policy
Politique de réduction.
MutableMemoryView m_grid_memory_values
Mémoire allouée pour la réduction sur une grille (de taille nb_bloc * sizeof(T))
unsigned int * m_grid_device_count
Entier utilisé pour compter le nombre de blocs ayant déjà fait leur partie de la réduction.