Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Partitioner.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Partitioner.h (C) 2000-2024 */
9/* */
10/* Algorithme de partitionnement de liste. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_PARTITIONER_H
13#define ARCANE_ACCELERATOR_PARTITIONER_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/ArrayView.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/NumArray.h"
20
21#include "arcane/accelerator/AcceleratorGlobal.h"
22#include "arcane/accelerator/core/RunQueue.h"
23#include "arcane/accelerator/CommonUtils.h"
24#include "arcane/accelerator/RunCommandLaunchInfo.h"
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29namespace Arcane::Accelerator::impl
30{
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
40class ARCANE_ACCELERATOR_EXPORT GenericPartitionerBase
41{
42 friend class GenericPartitionerIf;
43
44 public:
45
46 explicit GenericPartitionerBase(const RunQueue& queue);
47
48 protected:
49
50 Int32 _nbFirstPart() const;
51 SmallSpan<const Int32> _nbParts() const;
52 void _allocate();
53
54 protected:
55
56 RunQueue m_queue;
57 GenericDeviceStorage m_algo_storage;
58 DeviceStorage<int, 2> m_device_nb_list1_storage;
59 NumArray<Int32, MDDim1> m_host_nb_list1_storage;
60};
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
69{
70 public:
71
75 template <typename SelectLambda, typename InputIterator, typename OutputIterator>
78 {
79 RunQueue queue = s.m_queue;
81 RunCommand command = makeCommand(queue);
82 command << trace_info;
84 launch_info.beginExecute();
85 switch (exec_policy) {
86#if defined(ARCANE_COMPILING_CUDA)
88 size_t temp_storage_size = 0;
89 cudaStream_t stream = impl::CudaUtils::toNativeStream(&queue);
90 // Premier appel pour connaitre la taille pour l'allocation
91 int* nb_list1_ptr = nullptr;
92 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(nullptr, temp_storage_size,
94 select_lambda, stream));
95
96 s.m_algo_storage.allocate(temp_storage_size);
97 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
98 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(s.m_algo_storage.address(), temp_storage_size,
100 select_lambda, stream));
101 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
102 } break;
103#endif
104#if defined(ARCANE_COMPILING_HIP)
106 size_t temp_storage_size = 0;
107 // Premier appel pour connaitre la taille pour l'allocation
108 hipStream_t stream = impl::HipUtils::toNativeStream(&queue);
109 int* nb_list1_ptr = nullptr;
110 ARCANE_CHECK_HIP(rocprim::partition(nullptr, temp_storage_size, input_iter, output_iter,
112
113 s.m_algo_storage.allocate(temp_storage_size);
114 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
115
116 ARCANE_CHECK_HIP(rocprim::partition(s.m_algo_storage.address(), temp_storage_size, input_iter, output_iter,
118 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
119 } break;
120#endif
122 // Pas encore implémenté en multi-thread
123 [[fallthrough]];
128 for (Int32 i = 0; i < nb_item; ++i) {
129 auto v = *input_iter;
130 if (select_lambda(v)) {
131 *output_iter = v;
132 ++output_iter;
133 }
134 else {
135 --output2_iter;
136 *output2_iter = v;
137 }
138 ++input_iter;
139 }
141 s.m_host_nb_list1_storage[0] = nb_list1;
142 } break;
143 default:
144 ARCANE_FATAL(getBadPolicyMessage(exec_policy));
145 }
146 launch_info.endExecute();
147 }
148
152 template <typename Select1Lambda, typename Select2Lambda,
153 typename InputIterator, typename FirstOutputIterator,
154 typename SecondOutputIterator, typename UnselectedIterator>
162 const TraceInfo& trace_info = TraceInfo())
163 {
164 RunQueue queue = s.m_queue;
166 RunCommand command = makeCommand(queue);
167 command << trace_info;
169 launch_info.beginExecute();
170 switch (exec_policy) {
171#if defined(ARCANE_COMPILING_CUDA)
173 size_t temp_storage_size = 0;
174 cudaStream_t stream = impl::CudaUtils::toNativeStream(&queue);
175 // Premier appel pour connaitre la taille pour l'allocation
176 int* nb_list1_ptr = nullptr;
177 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(nullptr, temp_storage_size,
181
182 s.m_algo_storage.allocate(temp_storage_size);
183 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
184 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(s.m_algo_storage.address(), temp_storage_size,
188 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
189 } break;
190#endif
191#if defined(ARCANE_COMPILING_HIP)
193 size_t temp_storage_size = 0;
194 // Premier appel pour connaitre la taille pour l'allocation
195 hipStream_t stream = impl::HipUtils::toNativeStream(&queue);
196 int* nb_list1_ptr = nullptr;
197 using namespace rocprim;
198 ARCANE_CHECK_HIP(::rocprim::partition_three_way(nullptr, temp_storage_size, input_iter, first_output_iter,
201
202 s.m_algo_storage.allocate(temp_storage_size);
203 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
204
205 ARCANE_CHECK_HIP(partition_three_way(s.m_algo_storage.address(), temp_storage_size, input_iter, first_output_iter,
208 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
209 } break;
210#endif
212 // Pas encore implémenté en multi-thread
213 [[fallthrough]];
216 Int32 nb_first = 0;
217 Int32 nb_second = 0;
218 for (Int32 i = 0; i < nb_item; ++i) {
219 auto v = *input_iter;
220 bool is_1 = select1_lambda(v);
221 bool is_2 = select2_lambda(v);
222 if (is_1) {
225 ++nb_first;
226 }
227 else {
228 if (is_2) {
231 ++nb_second;
232 }
233 else {
234 *unselected_iter = v;
236 }
237 }
238 // Incrémenter l'itérateur à la fin car il est utilisé pour le positionnement
239 ++input_iter;
240 }
241 s.m_host_nb_list1_storage[0] = nb_first;
242 s.m_host_nb_list1_storage[1] = nb_second;
243 } break;
244 default:
245 ARCANE_FATAL(getBadPolicyMessage(exec_policy));
246 }
247 launch_info.endExecute();
248 }
249};
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
254} // namespace Arcane::Accelerator::impl
255
256namespace Arcane::Accelerator
257{
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
269{
270 public:
271
272 explicit GenericPartitioner(const RunQueue& queue)
274 {
275 _allocate();
276 }
277
278 public:
279
292 template <typename SelectLambda, typename SetterLambda>
306
323 template <typename InputIterator, typename OutputIterator, typename SelectLambda>
334
352 template <typename Setter1Lambda, typename Setter2Lambda, typename UnselectedSetterLambda,
353 typename Select1Lambda, typename Select2Lambda>
374
392 template <typename InputIterator, typename FirstOutputIterator,
393 typename SecondOutputIterator, typename UnselectedIterator,
394 typename Select1Lambda, typename Select2Lambda>
411
416 {
417 m_is_already_called = false;
418 return _nbFirstPart();
419 }
420
432 {
433 m_is_already_called = false;
434 return _nbParts();
435 }
436
437 private:
438
439 bool m_is_already_called = false;
440
441 private:
442
443 void _setCalled()
444 {
445 if (m_is_already_called)
446 ARCANE_FATAL("apply() has already been called for this instance");
447 m_is_already_called = true;
448 }
449};
450
451/*---------------------------------------------------------------------------*/
452/*---------------------------------------------------------------------------*/
453
454} // namespace Arcane::Accelerator
455
456/*---------------------------------------------------------------------------*/
457/*---------------------------------------------------------------------------*/
458
459#endif
460
461/*---------------------------------------------------------------------------*/
462/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Algorithme générique de partitionnement d'une liste.
SmallSpan< const Int32 > nbParts()
Nombre d'éléments de la première et deuxième partie de la liste.
Int32 nbFirstPart()
Nombre d'éléments de la première partie de la liste.
void applyWithIndex(Int32 nb_value, const Setter1Lambda setter1_lambda, const Setter2Lambda setter2_lambda, const UnselectedSetterLambda &unselected_setter_lambda, const Select1Lambda &select1_lambda, const Select2Lambda &select2_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue un partitionnement d'une liste en trois parties.
void applyIf(Int32 nb_value, InputIterator input_iter, OutputIterator output_iter, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue un partitionnement d'une liste en deux parties.
void applyWithIndex(Int32 nb_value, const SetterLambda &setter_lambda, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue un partitionnement d'une liste en deux parties.
void applyIf(Int32 nb_value, InputIterator input_iter, FirstOutputIterator first_output_iter, SecondOutputIterator second_output_iter, UnselectedIterator unselected_iter, const Select1Lambda &select1_lambda, const Select2Lambda &select2_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue un partitionnement d'une liste en trois parties.
Gestion d'une commande sur accélérateur.
File d'exécution pour un accélérateur.
eExecutionPolicy executionPolicy() const
Politique d'exécution de la file.
Definition RunQueue.cc:168
void copyToAsync(SmallSpan< DataType > dest_ptr, const RunQueue &queue)
Copie l'instance dans dest_ptr.
Gère l'allocation interne sur le device.
Definition CommonUtils.h:50
Classe de base pour effectuer un filtrage.
Definition Partitioner.h:41
Classe pour effectuer un partitionnement d'une liste.
Definition Partitioner.h:69
void apply3(GenericPartitionerBase &s, Int32 nb_item, InputIterator input_iter, FirstOutputIterator first_output_iter, SecondOutputIterator second_output_iter, UnselectedIterator unselected_iter, const Select1Lambda &select1_lambda, const Select2Lambda &select2_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue le partitionnement d'une liste en trois parties.
void apply(GenericPartitionerBase &s, Int32 nb_item, InputIterator input_iter, OutputIterator output_iter, const SelectLambda &select_lambda, const TraceInfo &trace_info=TraceInfo())
Effectue le partitionnement d'une liste en deux parties.
Definition Partitioner.h:76
Object temporaire pour conserver les informations d'exécution d'une commande et regrouper les tests.
Itérateur sur une lambda pour positionner une valeur via un index.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
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.
@ 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.