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.
Gère l'allocation interne sur le device pour un type donné.
Gère l'allocation interne sur le device.
Classe de base pour effectuer un filtrage.
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.
Classe pour effectuer un filtrage.
Classe pour effectuer un filtrage.
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.
Object temporaire pour conserver les informations d'exécution d'une commande et regrouper les tests.
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.