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"
860#include "arcane/accelerator/GenericReducer.h"
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour gérer les boucles sur les accélérateurs.
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.
Implémentation de la réduction pour le backend SYCL.
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 pour les arguments supplémentaires.
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.
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.
@ Atomic
Utilise des opérations atomiques entre les blocs.
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.