Arcane  v3.15.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
GenericPartitioner.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/* GenericPartitioner.h (C) 2000-2024 */
9/* */
10/* Algorithme de partitionnement de liste. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_GENERICPARTITIONER_H
13#define ARCANE_ACCELERATOR_GENERICPARTITIONER_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#if defined(ARCANE_COMPILING_SYCL)
27#endif
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane::Accelerator::impl
33{
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37/*!
38 * \internal
39 * \brief Classe de base pour effectuer un filtrage.
40 *
41 * Contient les arguments nécessaires pour effectuer le filtrage.
42 */
43class ARCANE_ACCELERATOR_EXPORT GenericPartitionerBase
44{
45 friend class GenericPartitionerIf;
46
47 public:
48
49 explicit GenericPartitionerBase(const RunQueue& queue);
50
51 protected:
52
53 Int32 _nbFirstPart() const;
54 SmallSpan<const Int32> _nbParts() const;
55 void _allocate();
56
57 protected:
58
59 RunQueue m_queue;
60 GenericDeviceStorage m_algo_storage;
61 DeviceStorage<int, 2> m_device_nb_list1_storage;
62 NumArray<Int32, MDDim1> m_host_nb_list1_storage;
63};
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67/*!
68 * \internal
69 * \brief Classe pour effectuer un partitionnement d'une liste.
70 */
72{
73 public:
74
75 /*!
76 * \brief Effectue le partitionnement d'une liste en deux parties.
77 */
78 template <typename SelectLambda, typename InputIterator, typename OutputIterator>
79 void apply(GenericPartitionerBase& s, Int32 nb_item, InputIterator input_iter, OutputIterator output_iter,
80 const SelectLambda& select_lambda, const TraceInfo& trace_info = TraceInfo())
81 {
82 RunQueue queue = s.m_queue;
83 eExecutionPolicy exec_policy = queue.executionPolicy();
84 RunCommand command = makeCommand(queue);
85 command << trace_info;
86 impl::RunCommandLaunchInfo launch_info(command, nb_item);
87 launch_info.beginExecute();
88 switch (exec_policy) {
89#if defined(ARCANE_COMPILING_CUDA)
91 size_t temp_storage_size = 0;
92 cudaStream_t stream = impl::CudaUtils::toNativeStream(&queue);
93 // Premier appel pour connaitre la taille pour l'allocation
94 int* nb_list1_ptr = nullptr;
95 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(nullptr, temp_storage_size,
96 input_iter, output_iter, nb_list1_ptr, nb_item,
97 select_lambda, stream));
98
99 s.m_algo_storage.allocate(temp_storage_size);
100 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
101 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(s.m_algo_storage.address(), temp_storage_size,
102 input_iter, output_iter, nb_list1_ptr, nb_item,
103 select_lambda, stream));
104 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
105 } break;
106#endif
107#if defined(ARCANE_COMPILING_HIP)
109 size_t temp_storage_size = 0;
110 // Premier appel pour connaitre la taille pour l'allocation
111 hipStream_t stream = impl::HipUtils::toNativeStream(&queue);
112 int* nb_list1_ptr = nullptr;
113 ARCANE_CHECK_HIP(rocprim::partition(nullptr, temp_storage_size, input_iter, output_iter,
114 nb_list1_ptr, nb_item, select_lambda, stream));
115
116 s.m_algo_storage.allocate(temp_storage_size);
117 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
118
119 ARCANE_CHECK_HIP(rocprim::partition(s.m_algo_storage.address(), temp_storage_size, input_iter, output_iter,
120 nb_list1_ptr, nb_item, select_lambda, stream));
121 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
122 } break;
123#endif
124#if defined(ARCANE_COMPILING_SYCL) && defined(__INTEL_LLVM_COMPILER)
126 // Seulement implémenté pour DPC++.
127 // Actuellement (dpc++ 2025.0), il n'y a pas l'équivalent avec SYCL de
128 // la méthode de partition de cub ou rocprim.
129 // Utilise la fonction 'stable_partition'. Cependant, cette fonction
130 // ne supporte pas si la mémoire uniquement sur accélérateur. De plus,
131 // il faut que InputIterator et OutputIterator remplissent le concept
132 // std::random_access_iterator ce qui n'est pas (notamment car il n'y a
133 // pas les opérateurs de copie ni de constructeur vide à cause de la lambda).
134 // Pour éviter tous ces problèmes, on alloue donc des tableaux temporaires
135 // pour l'appel à 'stable_sort' et on recopie les valerus en sortie.
136 using InputDataType = typename InputIterator::value_type;
137 using DataType = typename OutputIterator::value_type;
138 NumArray<DataType, MDDim1> tmp_output_numarray(nb_item);
139 NumArray<bool, MDDim1> tmp_select_numarray(nb_item);
140 auto tmp_output = tmp_output_numarray.to1DSmallSpan();
141 auto tmp_select = tmp_select_numarray.to1DSmallSpan();
142 {
143 auto command = makeCommand(queue);
144 command << RUNCOMMAND_LOOP1(iter, nb_item)
145 {
146 auto [i] = iter();
147 tmp_output[i] = input_iter[i];
148 };
149 }
150 auto tmp_select_lambda = [=](Int32 i) { return tmp_select[i]; };
151 sycl::queue sycl_queue = impl::SyclUtils::toNativeStream(queue);
152 auto policy = oneapi::dpl::execution::make_device_policy(sycl_queue);
153 auto output_after = oneapi::dpl::stable_partition(policy, tmp_output.begin(), tmp_output.end(), select_lambda);
154 queue.barrier();
155 Int32 nb_list1 = (output_after - tmp_output.begin());
156 Int32 nb_list2 = nb_item - nb_list1;
157 s.m_host_nb_list1_storage[0] = nb_list1;
158 //std::cerr << "NbList1=" << nb_list1 << " NbList2=" << nb_list2 << "\n";
159 {
160 // Recopie dans output les valeurs filtrées.
161 // Pour être cohérent avec 'cub' et 'rocprim', il faut inverser l'ordre des
162 // des valeurs de la liste pour les éléments ne remplissant pas la condition.
163 // Pour cela, on fait une boucle de taille (nb_list1 + nb_list/2) et chaque
164 // itération pour i>=nb_list1 gère deux éléments.
165 auto command = makeCommand(queue);
166 Int32 nb_iter2 = (nb_list2 / 2) + (nb_list2 % 2);
167 //std::cout << "NB_ITER2=" << nb_iter2 << "\n";
168 command << RUNCOMMAND_LOOP1(iter, (nb_list1 + nb_iter2))
169 {
170 auto [i] = iter();
171 if (i >= nb_list1) {
172 // Partie de la liste pour les valeurs ne remplissant par le critère.
173 Int32 j = i - nb_list1;
174 Int32 reverse_i = (nb_item - (j + 1));
175 auto x1 = tmp_output[i];
176 auto x2 = tmp_output[reverse_i];
177 output_iter[i] = tmp_output[reverse_i];
178 output_iter[reverse_i] = tmp_output[i];
179 }
180 else
181 output_iter[i] = tmp_output[i];
182 };
183 }
184 queue.barrier();
185 } break;
186#endif
188 // Pas encore implémenté en multi-thread
189 [[fallthrough]];
191 auto saved_output_iter = output_iter;
192 auto output2_iter = output_iter + nb_item;
193 for (Int32 i = 0; i < nb_item; ++i) {
194 auto v = *input_iter;
195 if (select_lambda(v)) {
196 *output_iter = v;
197 ++output_iter;
198 }
199 else {
200 --output2_iter;
201 *output2_iter = v;
202 }
203 ++input_iter;
204 }
205 Int32 nb_list1 = static_cast<Int32>(output_iter - saved_output_iter);
206 s.m_host_nb_list1_storage[0] = nb_list1;
207 } break;
208 default:
209 ARCANE_FATAL(getBadPolicyMessage(exec_policy));
210 }
211 launch_info.endExecute();
212 }
213
214 /*!
215 * \brief Effectue le partitionnement d'une liste en trois parties.
216 */
217 template <typename Select1Lambda, typename Select2Lambda,
218 typename InputIterator, typename FirstOutputIterator,
219 typename SecondOutputIterator, typename UnselectedIterator>
221 InputIterator input_iter,
222 FirstOutputIterator first_output_iter,
223 SecondOutputIterator second_output_iter,
224 UnselectedIterator unselected_iter,
225 const Select1Lambda& select1_lambda,
226 const Select2Lambda& select2_lambda,
227 const TraceInfo& trace_info = TraceInfo())
228 {
229 RunQueue queue = s.m_queue;
230 eExecutionPolicy exec_policy = queue.executionPolicy();
231 RunCommand command = makeCommand(queue);
232 command << trace_info;
233 impl::RunCommandLaunchInfo launch_info(command, nb_item);
234 launch_info.beginExecute();
235 switch (exec_policy) {
236#if defined(ARCANE_COMPILING_CUDA)
238 size_t temp_storage_size = 0;
239 cudaStream_t stream = impl::CudaUtils::toNativeStream(&queue);
240 // Premier appel pour connaitre la taille pour l'allocation
241 int* nb_list1_ptr = nullptr;
242 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(nullptr, temp_storage_size,
243 input_iter, first_output_iter, second_output_iter,
244 unselected_iter, nb_list1_ptr, nb_item,
245 select1_lambda, select2_lambda, stream));
246
247 s.m_algo_storage.allocate(temp_storage_size);
248 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
249 ARCANE_CHECK_CUDA(::cub::DevicePartition::If(s.m_algo_storage.address(), temp_storage_size,
250 input_iter, first_output_iter, second_output_iter,
251 unselected_iter, nb_list1_ptr, nb_item,
252 select1_lambda, select2_lambda, stream));
253 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
254 } break;
255#endif
256#if defined(ARCANE_COMPILING_HIP)
258 size_t temp_storage_size = 0;
259 // Premier appel pour connaitre la taille pour l'allocation
260 hipStream_t stream = impl::HipUtils::toNativeStream(&queue);
261 int* nb_list1_ptr = nullptr;
262 using namespace rocprim;
263 ARCANE_CHECK_HIP(::rocprim::partition_three_way(nullptr, temp_storage_size, input_iter, first_output_iter,
264 second_output_iter, unselected_iter,
265 nb_list1_ptr, nb_item, select1_lambda, select2_lambda, stream));
266
267 s.m_algo_storage.allocate(temp_storage_size);
268 nb_list1_ptr = s.m_device_nb_list1_storage.allocate();
269
270 ARCANE_CHECK_HIP(partition_three_way(s.m_algo_storage.address(), temp_storage_size, input_iter, first_output_iter,
271 second_output_iter, unselected_iter, nb_list1_ptr, nb_item,
272 select1_lambda, select2_lambda, stream));
273 s.m_device_nb_list1_storage.copyToAsync(s.m_host_nb_list1_storage, queue);
274 } break;
275#endif
277 // Pas encore implémenté en multi-thread
278 [[fallthrough]];
280 Int32 nb_first = 0;
281 Int32 nb_second = 0;
282 for (Int32 i = 0; i < nb_item; ++i) {
283 auto v = *input_iter;
284 bool is_1 = select1_lambda(v);
285 bool is_2 = select2_lambda(v);
286 if (is_1) {
287 *first_output_iter = v;
288 ++first_output_iter;
289 ++nb_first;
290 }
291 else {
292 if (is_2) {
293 *second_output_iter = v;
294 ++second_output_iter;
295 ++nb_second;
296 }
297 else {
298 *unselected_iter = v;
299 ++unselected_iter;
300 }
301 }
302 // Incrémenter l'itérateur à la fin car il est utilisé pour le positionnement
303 ++input_iter;
304 }
305 s.m_host_nb_list1_storage[0] = nb_first;
306 s.m_host_nb_list1_storage[1] = nb_second;
307 } break;
308 default:
309 ARCANE_FATAL(getBadPolicyMessage(exec_policy));
310 }
311 launch_info.endExecute();
312 }
313};
314
315/*---------------------------------------------------------------------------*/
316/*---------------------------------------------------------------------------*/
317
318} // namespace Arcane::Accelerator::impl
319
320namespace Arcane::Accelerator
321{
322
323/*---------------------------------------------------------------------------*/
324/*---------------------------------------------------------------------------*/
325/*!
326 * \brief Algorithme générique de partitionnement d'une liste.
327 *
328 * Cette classe fournit des algorithmes pour partitionner une liste en deux
329 * ou trois parties selon un critère fixé par l'utilisateur.
330 */
333{
334 public:
335
336 explicit GenericPartitioner(const RunQueue& queue)
338 {
339 _allocate();
340 }
341
342 public:
343
344 /*!
345 * \brief Effectue un partitionnement d'une liste en deux parties.
346 *
347 * Le nombre de valeurs de la liste est donné par \a nb_value.
348 * Les deux fonctions lambda \a select_lambda et \a setter_lambda permettent
349 * de partitionner et de positionner les valeurs de la liste.
350 *
351 * Après exécution, il est possible de récupérer le nombre d'éléments
352 * de la première partie de la liste via la méthode \a nbFirstPart().
353 *
354 * \snippet AcceleratorPartitionerUnitTest.cc SampleListPartitionerTwoWayIndex
355 */
356 template <typename SelectLambda, typename SetterLambda>
357 void applyWithIndex(Int32 nb_value, const SetterLambda& setter_lambda,
358 const SelectLambda& select_lambda, const TraceInfo& trace_info = TraceInfo())
359 {
360 if (nb_value == 0)
361 return;
362 _setCalled();
363 impl::GenericPartitionerBase* base_ptr = this;
365
366 impl::IndexIterator input_iter;
368 gf.apply(*base_ptr, nb_value, input_iter, out, select_lambda, trace_info);
369 }
370
371 /*!
372 * \brief Effectue un partitionnement d'une liste en deux parties.
373 *
374 * Le nombre de valeurs de la liste est donné par \a nb_value.
375 * Les valeurs en entrée sont fournies par l'itérateur \a input_iter et
376 * les valeurs en sorties par l'itérateur \a output_iterator. La fonction
377 * lambda \a select_lambda permet de sélectionner la partition utilisée :
378 * si le retour est \a true, la valeur sera dans la première partie de la liste,
379 * sinon elle sera dans la seconde. En sortie les valeurs de la deuxième
380 * partie sont rangées en ordre inverse de la liste d'entrée.
381 *
382 * Après exécution, il est possible de récupérer le nombre d'éléments
383 * de la première partie de la liste via la méthode \a nbFirstPart().
384 *
385 * \snippet AcceleratorPartitionerUnitTest.cc SampleListPartitionerTwoWayIf
386 */
387 template <typename InputIterator, typename OutputIterator, typename SelectLambda>
388 void applyIf(Int32 nb_value, InputIterator input_iter, OutputIterator output_iter,
389 const SelectLambda& select_lambda, const TraceInfo& trace_info = TraceInfo())
390 {
391 if (nb_value == 0)
392 return;
393 _setCalled();
394 impl::GenericPartitionerBase* base_ptr = this;
396 gf.apply(*base_ptr, nb_value, input_iter, output_iter, select_lambda, trace_info);
397 }
398
399 /*!
400 * \brief Effectue un partitionnement d'une liste en trois parties.
401 *
402 * Le nombre de valeurs de la liste est donné par \a nb_value.
403 * Les deux fonctions lambda \a select1_lambda et \a select2_lambda permettent
404 * de partitionner la liste avec l'algorithme suivant:
405 * - si select1_lambda() est vrai, la valeur sera positionnée via \a setter1_lambda,
406 * - sinon si select2_lambda() est vrai, la valeur sera positionnée via \a setter2_lambda,
407 * - sinon la valeur sera positionnée via \a unselected_setter_lambda.
408 *
409 * Les listes en sortie sont dans le même ordre qu'en entrée.
410 *
411 * Après exécution, il est possible de récupérer le nombre d'éléments
412 * de la première et de la deuxième liste la méthode \a nbParts().
413 *
414 * \snippet AcceleratorPartitionerUnitTest.cc SampleListPartitionerThreeWayIndex
415 */
416 template <typename Setter1Lambda, typename Setter2Lambda, typename UnselectedSetterLambda,
417 typename Select1Lambda, typename Select2Lambda>
418 void applyWithIndex(Int32 nb_value,
419 const Setter1Lambda setter1_lambda,
420 const Setter2Lambda setter2_lambda,
421 const UnselectedSetterLambda& unselected_setter_lambda,
422 const Select1Lambda& select1_lambda,
423 const Select2Lambda& select2_lambda,
424 const TraceInfo& trace_info = TraceInfo())
425 {
426 if (nb_value == 0)
427 return;
428 _setCalled();
429 impl::GenericPartitionerBase* base_ptr = this;
431 impl::IndexIterator input_iter;
432 impl::SetterLambdaIterator<Setter1Lambda> setter1_wrapper(setter1_lambda);
433 impl::SetterLambdaIterator<Setter2Lambda> setter2_wrapper(setter2_lambda);
434 impl::SetterLambdaIterator<UnselectedSetterLambda> unselected_setter_wrapper(unselected_setter_lambda);
435 gf.apply3(*base_ptr, nb_value, input_iter, setter1_wrapper, setter2_wrapper,
436 unselected_setter_wrapper, select1_lambda, select2_lambda, trace_info);
437 }
438
439 /*!
440 * \brief Effectue un partitionnement d'une liste en trois parties.
441 *
442 * Le nombre de valeurs de la liste est donné par \a nb_value.
443 * Les deux fonctions lambda \a select1_lambda et \a select2_lambda permettent
444 * de partitionner la liste avec l'algorithme suivant:
445 * - si select1_lambda() est vrai, la valeur ajoutée \a first_output_iter,
446 * - sinon si select2_lambda() est vrai, la valeur sera ajoutée à \a second_output_iter,
447 * - sinon la valeur sera ajoutée à \a unselected_iter.
448 *
449 * Les listes en sortie sont dans le même ordre qu'en entrée.
450 *
451 * Après exécution, il est possible de récupérer le nombre d'éléments
452 * de la première et de la deuxième liste la méthode \a nbParts().
453 *
454 * \snippet AcceleratorPartitionerUnitTest.cc SampleListPartitionerThreeWayIf
455 */
456 template <typename InputIterator, typename FirstOutputIterator,
457 typename SecondOutputIterator, typename UnselectedIterator,
458 typename Select1Lambda, typename Select2Lambda>
459 void applyIf(Int32 nb_value, InputIterator input_iter,
460 FirstOutputIterator first_output_iter,
461 SecondOutputIterator second_output_iter,
462 UnselectedIterator unselected_iter,
463 const Select1Lambda& select1_lambda,
464 const Select2Lambda& select2_lambda,
465 const TraceInfo& trace_info = TraceInfo())
466 {
467 if (nb_value == 0)
468 return;
469 _setCalled();
470 impl::GenericPartitionerBase* base_ptr = this;
472 gf.apply3(*base_ptr, nb_value, input_iter, first_output_iter, second_output_iter,
473 unselected_iter, select1_lambda, select2_lambda, trace_info);
474 }
475
476 /*!
477 * \brief Nombre d'éléments de la première partie de la liste.
478 */
480 {
481 m_is_already_called = false;
482 return _nbFirstPart();
483 }
484
485 /*!
486 * \brief Nombre d'éléments de la première et deuxième partie de la liste.
487 *
488 * Retourne une vue de deux valeurs. La première valeur contient le nombre
489 * d'éléments de la première liste et la seconde valeur le
490 * nombre d'éléments de la deuxième liste.
491 *
492 * Cette méthode n'est valide qu'après avoir appelé une méthode de partitionnement
493 * en trois parties.
494 */
496 {
497 m_is_already_called = false;
498 return _nbParts();
499 }
500
501 private:
502
503 bool m_is_already_called = false;
504
505 private:
506
507 void _setCalled()
508 {
509 if (m_is_already_called)
510 ARCANE_FATAL("apply() has already been called for this instance");
511 m_is_already_called = true;
512 }
513};
514
515/*---------------------------------------------------------------------------*/
516/*---------------------------------------------------------------------------*/
517
518} // namespace Arcane::Accelerator
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523#endif
524
525/*---------------------------------------------------------------------------*/
526/*---------------------------------------------------------------------------*/
#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 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.
void barrier() const
Bloque tant que toutes les commandes associées à la file ne sont pas terminées.
Definition RunQueue.cc:159
eExecutionPolicy executionPolicy() const
Politique d'exécution de la file.
Definition RunQueue.cc:169
void copyToAsync(SmallSpan< DataType > dest_ptr, const RunQueue &queue)
Copie l'instance dans dest_ptr.
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.
void beginExecute()
Indique qu'on commence l'exécution de la commande.
void endExecute()
Signale la fin de l'exécution.
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.
constexpr SmallSpan< DataType > to1DSmallSpan()
Vue 1D sur l'instance (uniquement si rank == 1)
Vue d'un tableau d'éléments de type T.
Definition Span.h:670
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.