12#ifndef ARCANE_ACCELERATOR_GENERICFILTERER_H 
   13#define ARCANE_ACCELERATOR_GENERICFILTERER_H 
   17#include "arcane/utils/ArrayView.h" 
   18#include "arcane/utils/FatalErrorException.h" 
   19#include "arcane/utils/NumArray.h" 
   20#include "arcane/utils/TraceInfo.h" 
   22#include "arcane/accelerator/core/RunQueue.h" 
   24#include "arcane/accelerator/AcceleratorGlobal.h" 
   25#include "arcane/accelerator/CommonUtils.h" 
   26#include "arcane/accelerator/RunCommandLaunchInfo.h" 
   28#include "arcane/accelerator/ScanImpl.h" 
   29#include "arcane/accelerator/MultiThreadAlgo.h" 
   34namespace Arcane::Accelerator::impl
 
   46class ARCANE_ACCELERATOR_EXPORT GenericFilteringBase
 
   48  template <
typename DataType, 
typename FlagType, 
typename OutputDataType>
 
   49  friend class GenericFilteringFlag;
 
   50  friend class GenericFilteringIf;
 
   51  friend class SyclGenericFilteringImpl;
 
   58  GenericFilteringBase();
 
   62  Int32 _nbOutputElement();
 
   64  void _allocateTemporaryStorage(
size_t size);
 
   65  int* _getDeviceNbOutPointer();
 
   66  void _copyDeviceNbOutToHostNbOut();
 
   68  bool _checkEmpty(
Int32 nb_value);
 
 
   96#if defined(ARCANE_COMPILING_SYCL) 
   98class SyclGenericFilteringImpl
 
  102  template <
typename SelectLambda, 
typename InputIterator, 
typename OutputIterator>
 
  104                    OutputIterator output_iter, SelectLambda select_lambda)
 
  107    using DataType = std::iterator_traits<OutputIterator>::value_type;
 
  108#if defined(ARCANE_USE_SCAN_ONEDPL) && defined(__INTEL_LLVM_COMPILER) 
  109    sycl::queue true_queue = AcceleratorUtils::toSyclNativeStream(queue);
 
  110    auto policy = oneapi::dpl::execution::make_device_policy(true_queue);
 
  111    auto out_iter = oneapi::dpl::copy_if(policy, input_iter, input_iter + nb_item, output_iter, select_lambda);
 
  112    Int32 nb_output = out_iter - output_iter;
 
  124        in_scan_data[i] = select_lambda(input_iter[i]) ? 1 : 0;
 
  128    SyclScanner<
false , 
Int32, ScannerSumOperator<Int32>> scanner;
 
  129    scanner.doScan(queue, in_scan_data, out_scan_data, 0);
 
  131    Int32 nb_output = out_scan_data[nb_item - 1];
 
  134    const bool do_verbose = 
false;
 
  135    if (do_verbose && nb_item < 1500)
 
  136      for (
int i = 0; i < nb_item; ++i) {
 
  137        std::cout << 
"out_data i=" << i << 
" out_data=" << out_scan_data[i]
 
  138                  << 
" in_data=" << in_scan_data[i] << 
" value=" << input_iter[i] << 
"\n ";
 
  145    out_copy.
resize(nb_output);
 
  146    auto out_copy_view = out_copy.
to1DSpan();
 
  152        if (in_scan_data[i] == 1)
 
  153          out_copy_view[out_scan_data[i] - 1] = input_iter[i];
 
  161        output_iter[i] = out_copy_view[i];
 
  181template <
typename DataType, 
typename FlagType, 
typename OutputDataType>
 
  190    if (output.
size() != nb_item)
 
  191      ARCANE_FATAL(
"Sizes are not equals: input={0} output={1}", nb_item, output.
size());
 
  192    [[maybe_unused]] 
const DataType* input_data = input.
data();
 
  193    [[maybe_unused]] DataType* output_data = output.
data();
 
  194    [[maybe_unused]] 
const FlagType* flag_data = flag.
data();
 
  198    switch (exec_policy) {
 
  199#if defined(ARCANE_COMPILING_CUDA) 
  201      size_t temp_storage_size = 0;
 
  202      cudaStream_t stream = AcceleratorUtils::toCudaNativeStream(queue);
 
  204      int* nb_out_ptr = 
nullptr;
 
  205      ARCANE_CHECK_CUDA(::cub::DeviceSelect::Flagged(
nullptr, temp_storage_size,
 
  206                                                     input_data, flag_data, output_data, nb_out_ptr, nb_item, stream));
 
  208      s._allocateTemporaryStorage(temp_storage_size);
 
  209      nb_out_ptr = s._getDeviceNbOutPointer();
 
  210      ARCANE_CHECK_CUDA(::cub::DeviceSelect::Flagged(s.m_algo_storage.address(), temp_storage_size,
 
  211                                                     input_data, flag_data, output_data, nb_out_ptr, nb_item, stream));
 
  212      s._copyDeviceNbOutToHostNbOut();
 
  215#if defined(ARCANE_COMPILING_HIP) 
  217      size_t temp_storage_size = 0;
 
  219      hipStream_t stream = AcceleratorUtils::toHipNativeStream(queue);
 
  220      int* nb_out_ptr = 
nullptr;
 
  221      ARCANE_CHECK_HIP(rocprim::select(
nullptr, temp_storage_size, input_data, flag_data, output_data,
 
  222                                       nb_out_ptr, nb_item, stream));
 
  224      s._allocateTemporaryStorage(temp_storage_size);
 
  225      nb_out_ptr = s._getDeviceNbOutPointer();
 
  227      ARCANE_CHECK_HIP(rocprim::select(s.m_algo_storage.address(), temp_storage_size, input_data, flag_data, output_data,
 
  228                                       nb_out_ptr, nb_item, stream));
 
  229      s._copyDeviceNbOutToHostNbOut();
 
  232#if defined(ARCANE_COMPILING_SYCL) 
  235      auto filter_lambda = [=](
Int32 input_index) -> 
bool { 
return flag[input_index] != 0; };
 
  236      auto setter_lambda = [=](
Int32 input_index, 
Int32 output_index) { output[output_index] = input[input_index]; };
 
  238      SyclGenericFilteringImpl::apply(s, nb_item, iter2, out, filter_lambda);
 
  246      for (
Int32 i = 0; i < nb_item; ++i) {
 
  248          output[index] = input[i];
 
 
  279  template <
bool InPlace, 
typename SelectLambda, 
typename InputIterator, 
typename OutputIterator>
 
  281             const SelectLambda& select_lambda, 
const TraceInfo& trace_info)
 
  287    command << trace_info;
 
  290    switch (exec_policy) {
 
  291#if defined(ARCANE_COMPILING_CUDA) 
  293      size_t temp_storage_size = 0;
 
  294      cudaStream_t stream = impl::CudaUtils::toNativeStream(queue);
 
  296      int* nb_out_ptr = 
nullptr;
 
  297      if constexpr (InPlace)
 
  298        ARCANE_CHECK_CUDA(::cub::DeviceSelect::If(
nullptr, temp_storage_size,
 
  299                                                  input_iter, nb_out_ptr, nb_item,
 
  300                                                  select_lambda, stream));
 
  302        ARCANE_CHECK_CUDA(::cub::DeviceSelect::If(
nullptr, temp_storage_size,
 
  303                                                  input_iter, output_iter, nb_out_ptr, nb_item,
 
  304                                                  select_lambda, stream));
 
  306      s._allocateTemporaryStorage(temp_storage_size);
 
  307      nb_out_ptr = s._getDeviceNbOutPointer();
 
  308      if constexpr (InPlace)
 
  309        ARCANE_CHECK_CUDA(::cub::DeviceSelect::If(s.m_algo_storage.address(), temp_storage_size,
 
  310                                                  input_iter, nb_out_ptr, nb_item,
 
  311                                                  select_lambda, stream));
 
  313        ARCANE_CHECK_CUDA(::cub::DeviceSelect::If(s.m_algo_storage.address(), temp_storage_size,
 
  314                                                  input_iter, output_iter, nb_out_ptr, nb_item,
 
  315                                                  select_lambda, stream));
 
  317      s._copyDeviceNbOutToHostNbOut();
 
  320#if defined(ARCANE_COMPILING_HIP) 
  322      size_t temp_storage_size = 0;
 
  324      hipStream_t stream = impl::HipUtils::toNativeStream(queue);
 
  325      int* nb_out_ptr = 
nullptr;
 
  329      ARCANE_CHECK_HIP(rocprim::select(
nullptr, temp_storage_size, input_iter, output_iter,
 
  330                                       nb_out_ptr, nb_item, select_lambda, stream));
 
  331      s._allocateTemporaryStorage(temp_storage_size);
 
  332      nb_out_ptr = s._getDeviceNbOutPointer();
 
  333      ARCANE_CHECK_HIP(rocprim::select(s.m_algo_storage.address(), temp_storage_size, input_iter, output_iter,
 
  334                                       nb_out_ptr, nb_item, select_lambda, 0));
 
  335      s._copyDeviceNbOutToHostNbOut();
 
  338#if defined(ARCANE_COMPILING_SYCL) 
  340      SyclGenericFilteringImpl::apply(s, nb_item, input_iter, output_iter, select_lambda);
 
  346        Int32 v = scanner.doFilter<InPlace>(launch_info.
loopRunInfo(), nb_item, input_iter, output_iter, select_lambda);
 
  353      for (
Int32 i = 0; i < nb_item; ++i) {
 
  354        if (select_lambda(*input_iter)) {
 
  355          *output_iter = *input_iter;
 
 
 
  394  ARCANE_DEPRECATED_REASON(
"Y2024: Use GenericFilterer(const RunQueue&) instead")
 
  438  template <
typename InputDataType, 
typename OutputDataType, 
typename FlagType>
 
  442    if (output.
size() != nb_value)
 
  443      ARCANE_FATAL(
"Sizes are not equals: input={0} output={1}", nb_value, output.
size());
 
  444    if (flag.
size() != nb_value)
 
  445      ARCANE_FATAL(
"Sizes are not equals: input={0} flag={1}", nb_value, flag.
size());
 
  447    if (_checkEmpty(nb_value))
 
  452    gf.apply(*base_ptr, input, output, flag);
 
 
  490  template <
typename DataType, 
typename SelectLambda>
 
  495    if (output.
size() != nb_value)
 
  496      ARCANE_FATAL(
"Sizes are not equals: input={0} output={1}", nb_value, output.
size());
 
  498      ARCANE_FATAL(
"Input and Output are the same. Use in place overload instead");
 
  499    if (_checkEmpty(nb_value))
 
  504    gf.
apply<
false>(*base_ptr, nb_value, input.
data(), output.
data(), select_lambda, trace_info);
 
 
  514  template <
typename DataType, 
typename SelectLambda>
 
  518    const Int32 nb_value = input_output.
size();
 
  519    if (_checkEmpty(nb_value))
 
  524    gf.
apply<
true>(*base_ptr, nb_value, input_output.
data(), input_output.
data(), select_lambda, trace_info);
 
 
  537  template <
typename InputIterator, 
typename OutputIterator, 
typename SelectLambda>
 
  538  void applyIf(
Int32 nb_value, InputIterator input_iter, OutputIterator output_iter,
 
  541    if (_checkEmpty(nb_value))
 
  546    gf.
apply<
false>(*base_ptr, nb_value, input_iter, output_iter, select_lambda, trace_info);
 
 
  582  template <
typename SelectLambda, 
typename SetterLambda>
 
  586    if (_checkEmpty(nb_value))
 
  593    gf.
apply<
false>(*base_ptr, nb_value, input_iter, out, select_lambda, trace_info);
 
 
  599    return _nbOutputElement();
 
 
 
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#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.
void applyIf(Int32 nb_value, InputIterator input_iter, OutputIterator output_iter, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique un filtre.
void applyWithIndex(Int32 nb_value, const SelectLambda &select_lambda, const SetterLambda &setter_lambda, const TraceInfo &trace_info=TraceInfo())
Applique un filtre avec une sélection suivant un index.
GenericFilterer(RunQueue *queue)
Créé une instance.
void applyIf(SmallSpan< DataType > input_output, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique un filtre en place.
void apply(SmallSpan< const InputDataType > input, SmallSpan< OutputDataType > output, SmallSpan< const FlagType > flag)
Applique un filtre.
void applyIf(SmallSpan< const DataType > input, SmallSpan< DataType > output, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Applique un filtre.
Int32 nbOutputElement()
Nombre d'éléments en sortie.
GenericFilterer(const RunQueue &queue)
Créé une instance.
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.
DeviceStorage< int > m_device_nb_out_storage
Mémoire sur le device du nombre de valeurs filtrées.
bool m_is_already_called
Indique si un appel est en cours.
NumArray< Int32, MDDim1 > m_host_nb_out_storage
Mémoire hôte pour le nombre de valeurs filtrées.
RunQueue m_queue
File d'exécution. Ne doit pas être nulle.
bool m_use_direct_host_storage
Indique quelle mémoire est utilisée pour le nombre de valeurs filtrées.
void apply(GenericFilteringBase &s, Int32 nb_item, InputIterator input_iter, OutputIterator output_iter, const SelectLambda &select_lambda, const TraceInfo &trace_info)
Applique le filtre.
Algorithmes avancée en mode multi-thread.
void beginExecute()
Indique qu'on commence l'exécution de la commande.
void endExecute()
Signale la fin de l'exécution.
const ForLoopRunInfo & loopRunInfo() const
Informations d'exécution de la boucle.
Itérateur sur une lambda pour positionner une valeur via un index.
Tableaux multi-dimensionnels pour les types numériques accessibles sur accélérateurs.
Span< const DataType > to1DSpan() const
Vue 1D constante sur l'instance.
constexpr SmallSpan< DataType > to1DSmallSpan()
Vue 1D sur l'instance (uniquement si rank == 1)
void resize(Int32 dim1_size)
Modifie la taille du tableau en gardant pas les valeurs actuelles.
Vue d'un tableau d'éléments de type T.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
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.
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.
std::int32_t Int32
Type entier signé sur 32 bits.