14#include "arccore/base/NotImplementedException.h"
15#include "arccore/base/IFunctor.h"
16#include "arccore/base/ForLoopRanges.h"
17#include "arccore/base/IObservable.h"
18#include "arccore/base/PlatformUtils.h"
19#include "arccore/base/FixedArray.h"
20#include "arccore/base/Profiling.h"
21#include "arccore/base/CheckedConvert.h"
22#include "arccore/base/FixedArray.h"
23#include "arccore/base/ForLoopRunInfo.h"
24#include "arccore/base/internal/DependencyInjection.h"
26#include "arccore/concurrency/IThreadImplementation.h"
27#include "arccore/concurrency/Task.h"
28#include "arccore/concurrency/ITaskImplementation.h"
29#include "arccore/concurrency/TaskFactory.h"
30#include "arccore/concurrency/ParallelFor.h"
31#include "arccore/concurrency/internal/TaskFactoryInternal.h"
36#include <unordered_set>
41#define TBB_PREVIEW_BLOCKED_RANGE_ND 1
49#define TBB_PREVIEW_WAITING_FOR_WORKERS 1
51#include <oneapi/tbb/concurrent_set.h>
52#include <oneapi/tbb/global_control.h>
73#if (TBB_VERSION_MAJOR > 2022) || (TBB_VERSION_MAJOR == 2022 && TBB_VERSION_MINOR > 0) || defined __TBB_blocked_nd_range_H
77template <
typename Value,
unsigned int N>
78using blocked_nd_range = tbb::blocked_nd_range<Value, N>;
82template <
typename Value,
unsigned int N>
83using blocked_nd_range = tbb::blocked_rangeNd<Value, N>;
92 constexpr Int32 cache_line_size = 64;
107 explicit ScopedExecInfo(
const ForLoopRunInfo& run_info)
108 : m_run_info(run_info)
114 ForLoopOneExecStat* ptr = run_info.execStat();
116 m_stat_info_ptr = ptr;
117 m_use_own_run_info =
false;
120 m_stat_info_ptr = isStatActive() ? &m_stat_info :
nullptr;
124#ifdef PRINT_STAT_INFO
125 if (m_stat_info_ptr) {
126 bool is_valid = m_run_info.traceInfo().isValid();
128 std::cout <<
"ADD_OWN_RUN_INFO nb_chunk=" << m_stat_info_ptr->nbChunk()
132 std::cout <<
"ADD_OWN_RUN_INFO nb_chunk=" << m_stat_info_ptr->nbChunk()
133 <<
" trace_name=" << m_run_info.traceInfo().traceInfo().name() <<
"\n";
136 if (m_stat_info_ptr && m_use_own_run_info) {
143 ForLoopOneExecStat* statInfo()
const {
return m_stat_info_ptr; }
144 bool isOwn()
const {
return m_use_own_run_info; }
148 ForLoopOneExecStat m_stat_info;
149 ForLoopOneExecStat* m_stat_info_ptr =
nullptr;
150 ForLoopRunInfo m_run_info;
152 bool m_use_own_run_info =
true;
158 inline int _currentTaskTreadIndex()
164 return tbb::this_task_arena::current_thread_index();
167 inline blocked_nd_range<Int32, 1>
170 return { { r.lowerBound<0>(), r.upperBound<0>() } };
173 inline blocked_nd_range<Int32, 2>
176 return { { r.lowerBound<0>(), r.upperBound<0>() },
177 { r.lowerBound<1>(), r.upperBound<1>() } };
180 inline blocked_nd_range<Int32, 3>
183 return { { r.lowerBound<0>(), r.upperBound<0>() },
184 { r.lowerBound<1>(), r.upperBound<1>() },
185 { r.lowerBound<2>(), r.upperBound<2>() } };
188 inline blocked_nd_range<Int32, 4>
191 return { { r.lowerBound<0>(), r.upperBound<0>() },
192 { r.lowerBound<1>(), r.upperBound<1>() },
193 { r.lowerBound<2>(), r.upperBound<2>() },
194 { r.lowerBound<3>(), r.upperBound<3>() } };
200 inline blocked_nd_range<Int32, 2>
203 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
204 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] } };
207 inline blocked_nd_range<Int32, 3>
210 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
211 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] },
212 { r.dim(2).begin(), r.dim(2).end(), grain_sizes[2] } };
215 inline blocked_nd_range<Int32, 4>
218 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
219 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] },
220 { r.dim(2).begin(), r.dim(2).end(), grain_sizes[2] },
221 { r.dim(3).begin(), r.dim(3).end(), grain_sizes[3] } };
228 _fromTBBRange(
const blocked_nd_range<Int32, 2>& r)
231 using ArrayExtentType = BoundsType::ArrayExtentType;
233 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin()));
234 auto s0 =
static_cast<Int32>(r.dim(0).size());
235 auto s1 =
static_cast<Int32>(r.dim(1).size());
236 BoundsType sizes(ArrayExtentType(s0, s1));
237 return { lower_bounds, sizes };
241 _fromTBBRange(
const blocked_nd_range<Int32, 3>& r)
244 using ArrayExtentType = BoundsType::ArrayExtentType;
246 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin(), r.dim(2).begin()));
247 auto s0 =
static_cast<Int32>(r.dim(0).size());
248 auto s1 =
static_cast<Int32>(r.dim(1).size());
249 auto s2 =
static_cast<Int32>(r.dim(2).size());
250 BoundsType sizes(ArrayExtentType(s0, s1, s2));
251 return { lower_bounds, sizes };
255 _fromTBBRange(
const blocked_nd_range<Int32, 4>& r)
258 using ArrayExtentType =
typename BoundsType::ArrayExtentType;
260 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin(), r.dim(2).begin(), r.dim(3).begin()));
261 auto s0 =
static_cast<Int32>(r.dim(0).size());
262 auto s1 =
static_cast<Int32>(r.dim(1).size());
263 auto s2 =
static_cast<Int32>(r.dim(2).size());
264 auto s3 =
static_cast<Int32>(r.dim(3).size());
265 BoundsType sizes(ArrayExtentType(s0, s1, s2, s3));
266 return { lower_bounds, sizes };
274class OneTBBTaskFunctor
285 void operator()()
const
310 static const int FUNCTOR_CLASS_SIZE = 32;
317 m_functor = f->clone(m_functor_buf.data(), FUNCTOR_CLASS_SIZE);
327 void wait()
override;
349class TBBTaskImplementation
354 template <
int RankValue>
361 class ARCCORE_ALIGNAS_PACKED(64) TaskThreadInfo
371 void setTaskIndex(
Integer v) { m_task_index = v; }
372 Integer taskIndex()
const {
return m_task_index; }
386 class TaskInfoLockGuard
390 TaskInfoLockGuard(TaskThreadInfo* tti,
Integer task_index)
392 , m_old_task_index(-1)
395 m_old_task_index = tti->taskIndex();
396 tti->setTaskIndex(task_index);
402 m_tti->setTaskIndex(m_old_task_index);
407 TaskThreadInfo* m_tti;
413 TBBTaskImplementation() =
default;
414 ~TBBTaskImplementation()
override;
487 bool m_is_active = false;
492 template <
int RankValue>
void
502class TBBTaskImplementation::Impl
505 :
public tbb::task_scheduler_observer
510 : tbb::task_scheduler_observer(p->m_main_arena)
514 void on_scheduler_entry(
bool is_worker)
override
516 m_p->notifyThreadCreated(is_worker);
518 void on_scheduler_exit(
bool is_worker)
override
520 m_p->notifyThreadDestroyed(is_worker);
528 : m_task_observer(this)
529 , m_thread_task_infos(cache_line_size)
531 m_nb_allowed_thread = tbb::info::default_concurrency();
535 : m_main_arena(nb_thread)
536 , m_task_observer(this)
537 , m_thread_task_infos(cache_line_size)
539 m_nb_allowed_thread = nb_thread;
546 TaskThreadInfo* threadTaskInfo(
Integer index) {
return &m_thread_task_infos[index]; }
550 Int32 m_nb_allowed_thread = 0;
558 int v = m_is_terminate_called.fetch_add(1);
568 m_main_arena.terminate();
569 m_task_observer.observe(
false);
570 oneapi::tbb::finalize(m_task_scheduler_handle);
575 void notifyThreadCreated(
bool is_worker)
579 if (m_nb_observed >= m_nb_allowed_thread)
582 std::thread::id my_thread_id = std::this_thread::get_id();
591 std::scoped_lock sl(m_thread_created_mutex);
592 if (m_constructed_thread_map.contains(my_thread_id))
594 m_constructed_thread_map.insert(my_thread_id);
597 Int32 nb_observed = ++m_nb_observed;
601 std::ostringstream ostr;
602 ostr <<
"TBB: CREATE THREAD"
603 <<
" nb_allowed=" << m_nb_allowed_thread
604 <<
" tbb_default_allowed=" << tbb::info::default_concurrency()
605 <<
" id=" << my_thread_id
606 <<
" arena_id=" << _currentTaskTreadIndex()
607 <<
" is_worker=" << is_worker
608 <<
" nb_observed=" << nb_observed
610 std::cout << ostr.str();
616 void notifyThreadDestroyed([[maybe_unused]]
bool is_worker)
627#if TBB_VERSION_MAJOR > 2021 || (TBB_VERSION_MAJOR == 2021 && TBB_VERSION_MINOR > 5)
628 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = oneapi::tbb::attach();
630 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = tbb::task_scheduler_handle::get();
635 tbb::task_arena m_main_arena;
642 std::mutex m_thread_created_mutex;
643 std::vector<TaskThreadInfo> m_thread_task_infos;
644 std::unordered_set<std::thread::id> m_constructed_thread_map;
645 std::atomic<Int32> m_is_terminate_called = 0;
654 std::cout <<
"TBB: TBBTaskImplementationInit nb_allowed_thread=" << m_nb_allowed_thread
655 <<
" id=" << std::this_thread::get_id()
656 <<
" version=" << TBB_VERSION_MAJOR <<
"." << TBB_VERSION_MINOR
659 m_thread_task_infos.resize(m_nb_allowed_thread);
660 m_task_observer.observe(
true);
661 Integer max_arena_size = m_nb_allowed_thread;
664 if (max_arena_size > 512)
665 max_arena_size = 512;
666 if (max_arena_size < 2)
670 for (
Integer i = 2; i < max_arena_size; ++i)
687 , m_stat_info(stat_info)
688 , m_nb_allowed_thread(nb_allowed_thread)
693 void operator()(tbb::blocked_range<Integer>& range)
const
697 std::ostringstream o;
699 <<
" id=" << std::this_thread::get_id()
700 <<
" max_allowed=" << m_nb_allowed_thread
701 <<
" range_begin=" << range.begin() <<
" range_size=" << range.size()
703 std::cout << o.str();
707 int tbb_index = _currentTaskTreadIndex();
708 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
709 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
710 tbb_index, m_nb_allowed_thread);
714 m_stat_info->incrementNbChunk();
715 m_functor->executeFunctor(range.begin(), CheckedConvert::toInteger(range.size()));
722 Int32 m_nb_allowed_thread;
731template <
int RankValue>
732class TBBMDParallelFor
738 , m_stat_info(stat_info)
739 , m_nb_allowed_thread(nb_allowed_thread)
744 void operator()(blocked_nd_range<Int32, RankValue>& range)
const
748 std::ostringstream o;
750 <<
" id=" << std::this_thread::get_id()
751 <<
" max_allowed=" << m_nb_allowed_thread
753 for (
Int32 i = 0; i < RankValue; ++i) {
754 auto r0 =
static_cast<Int32>(range.dim(i).begin());
755 auto r1 =
static_cast<Int32>(range.dim(i).size());
756 o <<
" range" << i <<
" (begin=" << r0 <<
" size=" << r1 <<
")";
759 std::cout << o.str();
763 int tbb_index = _currentTaskTreadIndex();
764 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
765 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
766 tbb_index, m_nb_allowed_thread);
770 m_stat_info->incrementNbChunk();
771 m_functor->executeFunctor(_fromTBBRange(range));
778 Int32 m_nb_allowed_thread;
801class TBBDeterministicParallelFor
809 , m_nb_thread(nb_thread)
810 , m_begin_index(begin_index)
812 , m_grain_size(grain_size)
815 , m_nb_block_per_thread(0)
820 if (m_grain_size > 0) {
821 m_block_size = m_grain_size;
822 if (m_block_size > 0) {
823 m_nb_block = m_size / m_block_size;
824 if ((m_size % m_block_size) != 0)
829 m_nb_block_per_thread = m_nb_block / m_nb_thread;
830 if ((m_nb_block % m_nb_thread) != 0)
831 ++m_nb_block_per_thread;
835 m_nb_block = m_nb_thread;
836 m_block_size = m_size / m_nb_block;
837 m_nb_block_per_thread = 1;
840 std::cout <<
"TBBDeterministicParallelFor: BEGIN=" << m_begin_index <<
" size=" << m_size
841 <<
" grain_size=" << m_grain_size
842 <<
" nb_block=" << m_nb_block <<
" nb_thread=" << m_nb_thread
843 <<
" nb_block_per_thread=" << m_nb_block_per_thread
844 <<
" block_size=" << m_block_size
845 <<
" block_size*nb_block=" << m_block_size * m_nb_block <<
'\n';
859 auto nb_iter =
static_cast<Integer>(range.size());
860 for (
Integer i = 0; i < nb_iter; ++i) {
861 Integer task_id = range.begin() + i;
862 for (
Integer k = 0, kn = m_nb_block_per_thread; k < kn; ++k) {
863 Integer block_id = task_id + (k * m_nb_thread);
864 if (block_id < m_nb_block)
865 _doBlock(task_id, block_id);
874 Integer iter_begin = block_id * m_block_size;
875 Integer iter_size = m_block_size;
876 if ((block_id + 1) == m_nb_block) {
878 iter_size = m_size - iter_begin;
880 iter_begin += m_begin_index;
882 if (TaskFactory::verboseLevel() >= 3) {
883 std::ostringstream o;
884 o <<
"TBB: DoBlock: BLOCK task_id=" << task_id <<
" block_id=" << block_id
885 <<
" iter_begin=" << iter_begin <<
" iter_size=" << iter_size <<
'\n';
886 std::cout << o.str();
891 auto r = tbb::blocked_range<int>(iter_begin, iter_begin + iter_size);
898 TBBTaskImplementation* m_impl;
899 const TBBParallelFor& m_tbb_for;
923 , m_stat_info(stat_info)
928 void operator()()
const
930 Integer nb_thread = m_options.maxThread();
932 Integer gsize = m_options.grainSize();
933 tbb::blocked_range<Integer> range(m_begin, m_begin + m_size);
935 std::cout <<
"TBB: TBBTaskImplementationInit ParallelForExecute begin=" << m_begin
936 <<
" size=" << m_size <<
" gsize=" << gsize
937 <<
" partitioner=" << (int)m_options.partitioner()
938 <<
" nb_thread=" << nb_thread
939 <<
" has_stat_info=" << (m_stat_info !=
nullptr)
943 range = tbb::blocked_range<Integer>(m_begin, m_begin + m_size, gsize);
946 tbb::parallel_for(range, pf, tbb::static_partitioner());
949 tbb::blocked_range<Integer> range2(0, nb_thread, 1);
951 tbb::parallel_for(range2, dpf);
954 tbb::parallel_for(range, pf);
959 TBBTaskImplementation* m_impl =
nullptr;
970template <
int RankValue>
975 MDParallelForExecute(TBBTaskImplementation* impl,
980 , m_tbb_range(_toTBBRange(range))
983 , m_stat_info(stat_info)
988 Int32 gsize = m_options.grainSize();
995 constexpr bool is_verbose =
false;
996 std::array<Int32, RankValue> range_extents = range.extents().asStdArray();
997 double ratio =
static_cast<double>(gsize) /
static_cast<double>(range.nbElement());
998 if constexpr (is_verbose) {
999 std::cout <<
"GSIZE=" << gsize <<
" rank=" << RankValue <<
" ratio=" << ratio;
1000 for (
Int32 i = 0; i < RankValue; ++i)
1001 std::cout <<
" range" << i <<
"=" << range_extents[i];
1004 Int32 index = RankValue - 1;
1005 Int32 remaining_grain = gsize;
1006 for (; index >= 0; --index) {
1007 Int32 current = range_extents[index];
1008 if constexpr (is_verbose)
1009 std::cout <<
"Check index=" << index <<
" remaining=" << remaining_grain <<
" current=" << current <<
"\n";
1010 if (remaining_grain > current) {
1011 all_grain_sizes[index] = current;
1012 remaining_grain /= current;
1015 all_grain_sizes[index] = remaining_grain;
1019 for (
Int32 i = 0; i < index; ++i)
1020 all_grain_sizes[i] = 1;
1021 if constexpr (is_verbose) {
1022 for (
Int32 i = 0; i < RankValue; ++i)
1023 std::cout <<
" grain" << i <<
"=" << all_grain_sizes[i];
1026 m_tbb_range = _toTBBRangeWithGrain(m_tbb_range, all_grain_sizes);
1032 void operator()()
const
1034 Integer nb_thread = m_options.maxThread();
1038 tbb::parallel_for(m_tbb_range, pf, tbb::static_partitioner());
1048 tbb::parallel_for(m_tbb_range, pf);
1054 TBBTaskImplementation* m_impl =
nullptr;
1055 blocked_nd_range<Int32, RankValue> m_tbb_range;
1064TBBTaskImplementation::
1065~TBBTaskImplementation()
1079 m_is_active = (nb_thread != 1);
1081 m_p =
new Impl(nb_thread);
1104 o <<
"OneTBBTaskImplementation"
1105 <<
" version=" << TBB_VERSION_STRING
1106 <<
" interface=" << TBB_INTERFACE_VERSION
1107 <<
" runtime_interface=" << TBB_runtime_interface_version();
1113void TBBTaskImplementation::
1116 ScopedExecInfo sei(loop_info.runInfo());
1120 Int32 begin = loop_info.beginIndex();
1121 Int32 size = loop_info.size();
1127 Integer nb_allowed_thread = m_p->nbAllowedThread();
1129 max_thread = nb_allowed_thread;
1132 std::cout <<
"TBB: TBBTaskImplementation executeParallelFor begin=" << begin
1133 <<
" size=" << size <<
" max_thread=" << max_thread
1134 <<
" grain_size=" << options.
grainSize()
1135 <<
" nb_allowed=" << nb_allowed_thread <<
'\n';
1138 if (max_thread == 1 || max_thread == 0) {
1144 ParallelLoopOptions true_options(options);
1146 true_options.setMaxThread(max_thread);
1148 ParallelForExecute pfe(
this, true_options, begin, size, f, stat_info);
1150 tbb::task_arena* used_arena =
nullptr;
1151 if (max_thread < nb_allowed_thread && max_thread < m_p->m_sub_arena_list.size())
1154 used_arena = &(m_p->m_main_arena);
1155 used_arena->execute(pfe);
1164 _executeParallelFor(loop_info);
1182 if (run_info.options().has_value())
1183 options = run_info.options().value();
1185 ScopedExecInfo sei(run_info);
1190 std::cout <<
"TBB: TBBTaskImplementation executeMDParallelFor nb_dim=" << RankValue
1191 <<
" nb_element=" << loop_ranges.nbElement()
1192 <<
" grain_size=" << options.
grainSize()
1193 <<
" name=" << run_info.traceInfo().traceInfo()
1194 <<
" has_stat_info=" << (stat_info !=
nullptr)
1200 if (max_thread == 1 || max_thread == 0) {
1201 functor->executeFunctor(loop_ranges);
1209 Integer nb_allowed_thread = m_p->nbAllowedThread();
1211 max_thread = nb_allowed_thread;
1212 tbb::task_arena* used_arena =
nullptr;
1213 if (max_thread < nb_allowed_thread)
1214 used_arena = m_p->m_sub_arena_list[max_thread];
1216 used_arena = &(m_p->m_main_arena);
1219 if constexpr (RankValue == 1) {
1220 auto range_1d = _toTBBRange(loop_ranges);
1226 Integer begin1 = CheckedConvert::toInteger(range_1d.dim(0).begin());
1227 Integer size1 = CheckedConvert::toInteger(range_1d.dim(0).size());
1229 used_arena->execute(pfe);
1233 used_arena->execute(pfe);
1266 return m_p->threadTaskInfo(thread_id);
1279 if (thread_id < 0 || thread_id >= m_p->nbAllowedThread())
1283 Int32 task_index = tti->taskIndex();
1284 if (task_index >= 0)
1296 tbb::task_group task_group;
1297 task_group.run(taskFunctor());
1308 tbb::task_group task_group;
1314 for (
Integer i = 0; i < n; ++i) {
1315 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1316 task_group.run(t->taskFunctor());
1319 for (
Integer i = 0; i < n; ++i) {
1320 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1331 if (m_task_group.isNull()) {
1332 m_task_group =
makeRef(
new tbb::task_group());
1334 m_task_group->run(taskFunctor());
1343 if (m_task_group.isNull()) {
1346 m_task_group->wait();
1363ARCANE_DI_REGISTER_PROVIDER(TBBTaskImplementation,
1364 DependencyInjection::ProviderProperty(
"TBBTaskImplementation"),
1365 ARCANE_DI_INTERFACES(ITaskImplementation),
1366 ARCANE_DI_EMPTY_CONSTRUCTOR());
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCCORE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCCORE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
Représente les limites d'un tableau multidimensionnel.
Interval d'itération complexe.
static void _setMaxAllowedThread(Int32 v)
Positionne le nombre maximum de thread à utiliser.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Tableau 1D de taille fixe.
Classe pour gérer le profiling d'une seule exécution d'une boucle.
Intervalle d'itération pour une boucle.
Informations d'exécution d'une boucle.
Interface d'un fonctor sur un interval d'itération multi-dimensionnel de dimension RankValue.
Interface d'un fonctor sur un interval d'itération.
virtual void executeFunctor(Int32 begin, Int32 size)=0
Exécute la méthode associée.
Interface d'un fonctor pour une tâche.
virtual void executeFunctor(const TaskContext &tc)=0
Exécute la méthode associé
Implémentation d'une fabrique de tâches.
Int32 nbAllowedThread() const
Nombre de threads utilisés au maximum pour gérer les tâches.
Interface d'une tâche concourante.
Classe permettant de récupérer le temps passé entre l'appel au constructeur et au destructeur.
Fonctor sur un interval d'itération instancié via une lambda fonction.
Exception lorsqu'une fonction n'est pas implémentée.
void wait() override
Méthode permettant d'attendre la fin de la tâche.
void launchAndWait() override
Lance la tâche et bloque jusqu'à ce qu'elle se termine.
void launch() override
Méthode permettant de lancer la tâche.
Caractéristiques d'un boucle 1D multi-thread.
Options d'exécution d'une boucle parallèle en multi-thread.
Integer grainSize() const
Taille d'un intervalle d'itération.
void mergeUnsetValues(const ParallelLoopOptions &po)
Fusionne les valeurs non modifiées de l'instance par celles de po.
Int32 maxThread() const
Nombre maximal de threads autorisés.
void setGrainSize(Integer v)
Positionne la taille (approximative) d'un intervalle d'itération.
void setMaxThread(Integer v)
Positionne le nombre maximal de threads autorisé.
@ Static
Utilise un partitionnement statique.
@ Deterministic
Utilise un partitionnement et un ordonnancement statique.
static Arcane::Impl::ForLoopStatInfoList * _threadLocalForLoopInstance()
static bool hasProfiling()
Indique si le profilage est actif.
Référence à une instance.
Implémentation déterministe de ParallelFor.
void operator()(tbb::blocked_range< Integer > &range) const
Opérateur pour un thread donné.
Exécuteur pour une boucle multi-dimension.
Exécuteur pour une boucle 1D.
std::atomic< Int32 > m_nb_observed
Compteur pour savoir combien de fois l'observateur a été appelé
std::vector< tbb::task_arena * > m_sub_arena_list
Tableau dont le i-ème élément contient la tbb::task_arena pour i thread.
Classe pour positionner TaskThreadInfo::taskIndex().
Int32 currentTaskThreadIndex() const final
Implémentation de TaskFactory::currentTaskThreadIndex().
void initialize(Int32 nb_thread) override
void executeParallelFor(const ComplexForLoopRanges< 1 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 1 > *functor) final
Exécute une boucle 1D en concurrence.
void executeParallelFor(Int32 begin, Int32 size, IRangeFunctor *f) final
Exécute le fonctor f en concurrence.
ITask * createRootTask(ITaskFunctor *f) override
Créé une tâche racine. L'implémentation doit recopier la valeur de f qui est soit un TaskFunctor,...
void printInfos(std::ostream &o) const final
Affiche les informations sur le runtime utilisé
void executeParallelFor(Int32 begin, Int32 size, const ParallelLoopOptions &options, IRangeFunctor *f) final
Exécute le fonctor f en concurrence.
void executeParallelFor(const ComplexForLoopRanges< 3 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 3 > *functor) final
Exécute une boucle 3D en concurrence.
void executeParallelFor(const ComplexForLoopRanges< 4 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 4 > *functor) final
Exécute une boucle 4D en concurrence.
TaskThreadInfo * currentTaskThreadInfo() const
Instance de TaskThreadInfo associé au thread courant.
void terminate() override
bool isActive() const final
Indique si l'implémentation est active.
void _executeMDParallelFor(const ComplexForLoopRanges< RankValue > &loop_ranges, IMDRangeFunctor< RankValue > *functor, const ForLoopRunInfo &run_info)
Exécution d'une boucle N-dimensions.
Int32 currentTaskIndex() const final
Implémentation de TaskFactory::currentTaskIndex().
void executeParallelFor(const ComplexForLoopRanges< 2 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 2 > *functor) final
Exécute une boucle 2D en concurrence.
Contexte d'éxecution d'une tâche.
static void notifyThreadCreated()
Notifie tous les observateurs de création de thread.
static const ParallelLoopOptions & defaultParallelLoopOptions()
Valeurs par défaut d'exécution d'une boucle parallèle.
static Integer verboseLevel()
Niveau de verbosité
static void setDefaultParallelLoopOptions(const ParallelLoopOptions &v)
Positionne les valeurs par défaut d'exécution d'une boucle parallèle.
static Int32 currentTaskThreadIndex()
Indice (entre 0 et nbAllowedThread()-1) du thread exécutant la tâche actuelle.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type représentant un entier.
SimpleForLoopRanges< 1 > makeLoopRanges(Int32 n1)
Crée une plage d'itération [0,n1[, [0,n2[.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.