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"
40#define TBB_PREVIEW_BLOCKED_RANGE_ND 1
48#define TBB_PREVIEW_WAITING_FOR_WORKERS 1
50#include <oneapi/tbb/concurrent_set.h>
51#include <oneapi/tbb/global_control.h>
72#if (TBB_VERSION_MAJOR > 2022) || (TBB_VERSION_MAJOR == 2022 && TBB_VERSION_MINOR > 0) || defined __TBB_blocked_nd_range_H
76template <
typename Value,
unsigned int N>
77using blocked_nd_range = tbb::blocked_nd_range<Value, N>;
81template <
typename Value,
unsigned int N>
82using blocked_nd_range = tbb::blocked_rangeNd<Value, N>;
91 constexpr Int32 cache_line_size = 64;
106 explicit ScopedExecInfo(
const ForLoopRunInfo& run_info)
107 : m_run_info(run_info)
113 ForLoopOneExecStat* ptr = run_info.execStat();
115 m_stat_info_ptr = ptr;
116 m_use_own_run_info =
false;
119 m_stat_info_ptr = isStatActive() ? &m_stat_info :
nullptr;
123#ifdef PRINT_STAT_INFO
124 if (m_stat_info_ptr) {
125 bool is_valid = m_run_info.traceInfo().isValid();
127 std::cout <<
"ADD_OWN_RUN_INFO nb_chunk=" << m_stat_info_ptr->nbChunk()
131 std::cout <<
"ADD_OWN_RUN_INFO nb_chunk=" << m_stat_info_ptr->nbChunk()
132 <<
" trace_name=" << m_run_info.traceInfo().traceInfo().name() <<
"\n";
135 if (m_stat_info_ptr && m_use_own_run_info) {
136 ProfilingRegistry::_threadLocalForLoopInstance()->merge(*m_stat_info_ptr, m_run_info.traceInfo());
142 ForLoopOneExecStat* statInfo()
const {
return m_stat_info_ptr; }
143 bool isOwn()
const {
return m_use_own_run_info; }
147 ForLoopOneExecStat m_stat_info;
148 ForLoopOneExecStat* m_stat_info_ptr =
nullptr;
149 ForLoopRunInfo m_run_info;
151 bool m_use_own_run_info =
true;
157 inline int _currentTaskTreadIndex()
163 return tbb::this_task_arena::current_thread_index();
166 inline blocked_nd_range<Int32, 1>
169 return { { r.lowerBound<0>(), r.upperBound<0>() } };
172 inline blocked_nd_range<Int32, 2>
175 return { { r.lowerBound<0>(), r.upperBound<0>() },
176 { r.lowerBound<1>(), r.upperBound<1>() } };
179 inline blocked_nd_range<Int32, 3>
182 return { { r.lowerBound<0>(), r.upperBound<0>() },
183 { r.lowerBound<1>(), r.upperBound<1>() },
184 { r.lowerBound<2>(), r.upperBound<2>() } };
187 inline blocked_nd_range<Int32, 4>
190 return { { r.lowerBound<0>(), r.upperBound<0>() },
191 { r.lowerBound<1>(), r.upperBound<1>() },
192 { r.lowerBound<2>(), r.upperBound<2>() },
193 { r.lowerBound<3>(), r.upperBound<3>() } };
199 inline blocked_nd_range<Int32, 2>
202 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
203 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] } };
206 inline blocked_nd_range<Int32, 3>
209 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
210 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] },
211 { r.dim(2).begin(), r.dim(2).end(), grain_sizes[2] } };
214 inline blocked_nd_range<Int32, 4>
217 return { { r.dim(0).begin(), r.dim(0).end(), grain_sizes[0] },
218 { r.dim(1).begin(), r.dim(1).end(), grain_sizes[1] },
219 { r.dim(2).begin(), r.dim(2).end(), grain_sizes[2] },
220 { r.dim(3).begin(), r.dim(3).end(), grain_sizes[3] } };
227 _fromTBBRange(
const blocked_nd_range<Int32, 2>& r)
230 using ArrayExtentType = BoundsType::ArrayExtentType;
232 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin()));
233 auto s0 =
static_cast<Int32>(r.dim(0).size());
234 auto s1 =
static_cast<Int32>(r.dim(1).size());
235 BoundsType sizes(ArrayExtentType(s0, s1));
236 return { lower_bounds, sizes };
240 _fromTBBRange(
const blocked_nd_range<Int32, 3>& r)
243 using ArrayExtentType = BoundsType::ArrayExtentType;
245 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin(), r.dim(2).begin()));
246 auto s0 =
static_cast<Int32>(r.dim(0).size());
247 auto s1 =
static_cast<Int32>(r.dim(1).size());
248 auto s2 =
static_cast<Int32>(r.dim(2).size());
249 BoundsType sizes(ArrayExtentType(s0, s1, s2));
250 return { lower_bounds, sizes };
254 _fromTBBRange(
const blocked_nd_range<Int32, 4>& r)
257 using ArrayExtentType =
typename BoundsType::ArrayExtentType;
259 BoundsType lower_bounds(ArrayExtentType(r.dim(0).begin(), r.dim(1).begin(), r.dim(2).begin(), r.dim(3).begin()));
260 auto s0 =
static_cast<Int32>(r.dim(0).size());
261 auto s1 =
static_cast<Int32>(r.dim(1).size());
262 auto s2 =
static_cast<Int32>(r.dim(2).size());
263 auto s3 =
static_cast<Int32>(r.dim(3).size());
264 BoundsType sizes(ArrayExtentType(s0, s1, s2, s3));
265 return { lower_bounds, sizes };
273class OneTBBTaskFunctor
284 void operator()()
const
309 static const int FUNCTOR_CLASS_SIZE = 32;
316 m_functor = f->clone(m_functor_buf.data(), FUNCTOR_CLASS_SIZE);
344class TBBTaskImplementation
349 template <
int RankValue>
350 class MDParallelForExecute;
356 class ARCCORE_ALIGNAS_PACKED(64) TaskThreadInfo
366 void setTaskIndex(
Integer v) { m_task_index = v; }
367 Integer taskIndex()
const {
return m_task_index; }
381 class TaskInfoLockGuard
385 TaskInfoLockGuard(TaskThreadInfo* tti,
Integer task_index)
387 , m_old_task_index(-1)
390 m_old_task_index = tti->taskIndex();
391 tti->setTaskIndex(task_index);
397 m_tti->setTaskIndex(m_old_task_index);
402 TaskThreadInfo* m_tti;
408 TBBTaskImplementation() =
default;
409 ~TBBTaskImplementation()
override;
414 void initialize(
Int32 nb_thread)
override;
415 void terminate()
override;
435 _executeMDParallelFor<1>(loop_ranges, functor, run_info);
441 _executeMDParallelFor<2>(loop_ranges, functor, run_info);
447 _executeMDParallelFor<3>(loop_ranges, functor, run_info);
453 _executeMDParallelFor<4>(loop_ranges, functor, run_info);
482 bool m_is_active = false;
487 template <
int RankValue>
void
497class TBBTaskImplementation::Impl
500 :
public tbb::task_scheduler_observer
505 : tbb::task_scheduler_observer(p->m_main_arena)
509 void on_scheduler_entry(
bool is_worker)
override
511 m_p->notifyThreadCreated(is_worker);
513 void on_scheduler_exit(
bool is_worker)
override
515 m_p->notifyThreadDestroyed(is_worker);
523 : m_task_observer(
this)
524 , m_thread_task_infos(cache_line_size)
526 m_nb_allowed_thread = tbb::info::default_concurrency();
529 Impl(
Int32 nb_thread)
530 : m_main_arena(nb_thread)
531 , m_task_observer(
this)
532 , m_thread_task_infos(cache_line_size)
534 m_nb_allowed_thread = nb_thread;
541 TaskThreadInfo* threadTaskInfo(
Integer index) {
return &m_thread_task_infos[index]; }
545 Int32 m_nb_allowed_thread = 0;
557 m_main_arena.terminate();
558 m_task_observer.observe(
false);
559 oneapi::tbb::finalize(m_task_scheduler_handle);
564 void notifyThreadCreated(
bool is_worker)
566 std::thread::id my_thread_id = std::this_thread::get_id();
574 if (m_constructed_thread_map.contains(my_thread_id))
576 m_constructed_thread_map.insert(my_thread_id);
580 std::ostringstream ostr;
581 ostr <<
"TBB: CREATE THREAD"
582 <<
" nb_allowed=" << m_nb_allowed_thread
583 <<
" tbb_default_allowed=" << tbb::info::default_concurrency()
584 <<
" id=" << my_thread_id
585 <<
" arena_id=" << _currentTaskTreadIndex()
586 <<
" is_worker=" << is_worker
588 std::cout << ostr.str();
590 TaskFactoryInternal::notifyThreadCreated();
594 void notifyThreadDestroyed([[maybe_unused]]
bool is_worker)
605#if TBB_VERSION_MAJOR > 2021 || (TBB_VERSION_MAJOR == 2021 && TBB_VERSION_MINOR > 5)
606 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = oneapi::tbb::attach();
608 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = tbb::task_scheduler_handle::get();
613 tbb::task_arena m_main_arena;
619 TaskObserver m_task_observer;
620 std::mutex m_thread_created_mutex;
621 std::vector<TaskThreadInfo> m_thread_task_infos;
622 tbb::concurrent_set<std::thread::id> m_constructed_thread_map;
625 ConcurrencyBase::_setMaxAllowedThread(m_nb_allowed_thread);
628 std::cout <<
"TBB: TBBTaskImplementationInit nb_allowed_thread=" << m_nb_allowed_thread
629 <<
" id=" << std::this_thread::get_id()
630 <<
" version=" << TBB_VERSION_MAJOR <<
"." << TBB_VERSION_MINOR
633 m_thread_task_infos.resize(m_nb_allowed_thread);
634 m_task_observer.observe(
true);
635 Integer max_arena_size = m_nb_allowed_thread;
638 if (max_arena_size > 512)
639 max_arena_size = 512;
640 if (max_arena_size < 2)
644 for (
Integer i = 2; i < max_arena_size; ++i)
661 , m_stat_info(stat_info)
662 , m_nb_allowed_thread(nb_allowed_thread)
667 void operator()(tbb::blocked_range<Integer>& range)
const
671 std::ostringstream o;
673 <<
" id=" << std::this_thread::get_id()
674 <<
" max_allowed=" << m_nb_allowed_thread
675 <<
" range_begin=" << range.begin() <<
" range_size=" << range.size()
677 std::cout << o.str();
681 int tbb_index = _currentTaskTreadIndex();
682 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
683 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
684 tbb_index, m_nb_allowed_thread);
688 m_stat_info->incrementNbChunk();
689 m_functor->executeFunctor(range.begin(), CheckedConvert::toInteger(range.size()));
696 Int32 m_nb_allowed_thread;
705template <
int RankValue>
706class TBBMDParallelFor
712 , m_stat_info(stat_info)
713 , m_nb_allowed_thread(nb_allowed_thread)
718 void operator()(blocked_nd_range<Int32, RankValue>& range)
const
722 std::ostringstream o;
724 <<
" id=" << std::this_thread::get_id()
725 <<
" max_allowed=" << m_nb_allowed_thread
727 for (
Int32 i = 0; i < RankValue; ++i) {
728 auto r0 =
static_cast<Int32>(range.dim(i).begin());
729 auto r1 =
static_cast<Int32>(range.dim(i).size());
730 o <<
" range" << i <<
" (begin=" << r0 <<
" size=" << r1 <<
")";
733 std::cout << o.str();
737 int tbb_index = _currentTaskTreadIndex();
738 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
739 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
740 tbb_index, m_nb_allowed_thread);
744 m_stat_info->incrementNbChunk();
745 m_functor->executeFunctor(_fromTBBRange(range));
752 Int32 m_nb_allowed_thread;
775class TBBDeterministicParallelFor
783 , m_nb_thread(nb_thread)
784 , m_begin_index(begin_index)
786 , m_grain_size(grain_size)
789 , m_nb_block_per_thread(0)
794 if (m_grain_size > 0) {
795 m_block_size = m_grain_size;
796 if (m_block_size > 0) {
797 m_nb_block = m_size / m_block_size;
798 if ((m_size % m_block_size) != 0)
803 m_nb_block_per_thread = m_nb_block / m_nb_thread;
804 if ((m_nb_block % m_nb_thread) != 0)
805 ++m_nb_block_per_thread;
809 m_nb_block = m_nb_thread;
810 m_block_size = m_size / m_nb_block;
811 m_nb_block_per_thread = 1;
814 std::cout <<
"TBBDeterministicParallelFor: BEGIN=" << m_begin_index <<
" size=" << m_size
815 <<
" grain_size=" << m_grain_size
816 <<
" nb_block=" << m_nb_block <<
" nb_thread=" << m_nb_thread
817 <<
" nb_block_per_thread=" << m_nb_block_per_thread
818 <<
" block_size=" << m_block_size
819 <<
" block_size*nb_block=" << m_block_size * m_nb_block <<
'\n';
833 auto nb_iter =
static_cast<Integer>(range.size());
834 for (
Integer i = 0; i < nb_iter; ++i) {
835 Integer task_id = range.begin() + i;
836 for (
Integer k = 0, kn = m_nb_block_per_thread; k < kn; ++k) {
837 Integer block_id = task_id + (k * m_nb_thread);
838 if (block_id < m_nb_block)
839 _doBlock(task_id, block_id);
848 Integer iter_begin = block_id * m_block_size;
849 Integer iter_size = m_block_size;
850 if ((block_id + 1) == m_nb_block) {
852 iter_size = m_size - iter_begin;
854 iter_begin += m_begin_index;
856 if (TaskFactory::verboseLevel() >= 3) {
857 std::ostringstream o;
858 o <<
"TBB: DoBlock: BLOCK task_id=" << task_id <<
" block_id=" << block_id
859 <<
" iter_begin=" << iter_begin <<
" iter_size=" << iter_size <<
'\n';
860 std::cout << o.str();
865 auto r = tbb::blocked_range<int>(iter_begin, iter_begin + iter_size);
872 TBBTaskImplementation* m_impl;
873 const TBBParallelFor& m_tbb_for;
897 , m_stat_info(stat_info)
902 void operator()()
const
904 Integer nb_thread = m_options.maxThread();
906 Integer gsize = m_options.grainSize();
907 tbb::blocked_range<Integer> range(m_begin, m_begin + m_size);
909 std::cout <<
"TBB: TBBTaskImplementationInit ParallelForExecute begin=" << m_begin
910 <<
" size=" << m_size <<
" gsize=" << gsize
911 <<
" partitioner=" << (int)m_options.partitioner()
912 <<
" nb_thread=" << nb_thread
913 <<
" has_stat_info=" << (m_stat_info !=
nullptr)
917 range = tbb::blocked_range<Integer>(m_begin, m_begin + m_size, gsize);
920 tbb::parallel_for(range, pf, tbb::static_partitioner());
923 tbb::blocked_range<Integer> range2(0, nb_thread, 1);
925 tbb::parallel_for(range2, dpf);
928 tbb::parallel_for(range, pf);
933 TBBTaskImplementation* m_impl =
nullptr;
944template <
int RankValue>
945class TBBTaskImplementation::MDParallelForExecute
949 MDParallelForExecute(TBBTaskImplementation* impl,
954 , m_tbb_range(_toTBBRange(range))
957 , m_stat_info(stat_info)
962 Int32 gsize = m_options.grainSize();
969 constexpr bool is_verbose =
false;
970 std::array<Int32, RankValue> range_extents = range.extents().asStdArray();
971 double ratio =
static_cast<double>(gsize) /
static_cast<double>(range.nbElement());
972 if constexpr (is_verbose) {
973 std::cout <<
"GSIZE=" << gsize <<
" rank=" << RankValue <<
" ratio=" << ratio;
974 for (
Int32 i = 0; i < RankValue; ++i)
975 std::cout <<
" range" << i <<
"=" << range_extents[i];
978 Int32 index = RankValue - 1;
979 Int32 remaining_grain = gsize;
980 for (; index >= 0; --index) {
981 Int32 current = range_extents[index];
982 if constexpr (is_verbose)
983 std::cout <<
"Check index=" << index <<
" remaining=" << remaining_grain <<
" current=" << current <<
"\n";
984 if (remaining_grain > current) {
985 all_grain_sizes[index] = current;
986 remaining_grain /= current;
989 all_grain_sizes[index] = remaining_grain;
993 for (Int32 i = 0; i < index; ++i)
994 all_grain_sizes[i] = 1;
995 if constexpr (is_verbose) {
996 for (Int32 i = 0; i < RankValue; ++i)
997 std::cout <<
" grain" << i <<
"=" << all_grain_sizes[i];
1000 m_tbb_range = _toTBBRangeWithGrain(m_tbb_range, all_grain_sizes);
1006 void operator()()
const
1008 Integer nb_thread = m_options.maxThread();
1009 TBBMDParallelFor<RankValue> pf(m_functor, nb_thread, m_stat_info);
1011 if (m_options.partitioner() == ParallelLoopOptions::Partitioner::Static) {
1012 tbb::parallel_for(m_tbb_range, pf, tbb::static_partitioner());
1014 else if (m_options.partitioner() == ParallelLoopOptions::Partitioner::Deterministic) {
1016 ARCCORE_THROW(NotImplementedException,
"ParallelLoopOptions::Partitioner::Deterministic for multi-dimensionnal loops");
1022 tbb::parallel_for(m_tbb_range, pf);
1028 TBBTaskImplementation* m_impl =
nullptr;
1029 blocked_nd_range<Int32, RankValue> m_tbb_range;
1030 IMDRangeFunctor<RankValue>* m_functor =
nullptr;
1031 ParallelLoopOptions m_options;
1032 ForLoopOneExecStat* m_stat_info =
nullptr;
1038TBBTaskImplementation::
1039~TBBTaskImplementation()
1047void TBBTaskImplementation::
1048initialize(
Int32 nb_thread)
1052 m_is_active = (nb_thread != 1);
1054 m_p =
new Impl(nb_thread);
1065void TBBTaskImplementation::
1077 o <<
"OneTBBTaskImplementation"
1078 <<
" version=" << TBB_VERSION_STRING
1079 <<
" interface=" << TBB_INTERFACE_VERSION
1080 <<
" runtime_interface=" << TBB_runtime_interface_version();
1086void TBBTaskImplementation::
1089 ScopedExecInfo sei(loop_info.runInfo());
1093 Int32 begin = loop_info.beginIndex();
1094 Int32 size = loop_info.size();
1100 Integer nb_allowed_thread = m_p->nbAllowedThread();
1102 max_thread = nb_allowed_thread;
1105 std::cout <<
"TBB: TBBTaskImplementation executeParallelFor begin=" << begin
1106 <<
" size=" << size <<
" max_thread=" << max_thread
1107 <<
" grain_size=" << options.
grainSize()
1108 <<
" nb_allowed=" << nb_allowed_thread <<
'\n';
1111 if (max_thread == 1 || max_thread == 0) {
1117 ParallelLoopOptions true_options(options);
1119 true_options.setMaxThread(max_thread);
1121 ParallelForExecute pfe(
this, true_options, begin, size, f, stat_info);
1123 tbb::task_arena* used_arena =
nullptr;
1124 if (max_thread < nb_allowed_thread && max_thread < m_p->m_sub_arena_list.size())
1127 used_arena = &(m_p->m_main_arena);
1128 used_arena->execute(pfe);
1137 _executeParallelFor(loop_info);
1149template <
int RankValue>
void TBBTaskImplementation::
1155 if (run_info.options().has_value())
1156 options = run_info.options().value();
1158 ScopedExecInfo sei(run_info);
1163 std::cout <<
"TBB: TBBTaskImplementation executeMDParallelFor nb_dim=" << RankValue
1164 <<
" nb_element=" << loop_ranges.nbElement()
1165 <<
" grain_size=" << options.
grainSize()
1166 <<
" name=" << run_info.traceInfo().traceInfo()
1167 <<
" has_stat_info=" << (stat_info !=
nullptr)
1173 if (max_thread == 1 || max_thread == 0) {
1179 ParallelLoopOptions true_options(options);
1182 Integer nb_allowed_thread = m_p->nbAllowedThread();
1184 max_thread = nb_allowed_thread;
1185 tbb::task_arena* used_arena =
nullptr;
1186 if (max_thread < nb_allowed_thread)
1187 used_arena = m_p->m_sub_arena_list[max_thread];
1189 used_arena = &(m_p->m_main_arena);
1192 if constexpr (RankValue == 1) {
1193 auto range_1d = _toTBBRange(loop_ranges);
1198 LambdaRangeFunctorT<
decltype(x1)> functor_1d(x1);
1199 Integer begin1 = CheckedConvert::toInteger(range_1d.dim(0).begin());
1200 Integer size1 = CheckedConvert::toInteger(range_1d.dim(0).size());
1202 used_arena->execute(pfe);
1205 MDParallelForExecute<RankValue> pfe(
this, true_options, loop_ranges, functor, stat_info);
1206 used_arena->execute(pfe);
1239 return m_p->threadTaskInfo(thread_id);
1252 if (thread_id < 0 || thread_id >= m_p->nbAllowedThread())
1256 Int32 task_index = tti->taskIndex();
1257 if (task_index >= 0)
1269 tbb::task_group task_group;
1270 task_group.run(taskFunctor());
1281 tbb::task_group task_group;
1287 for (
Integer i = 0; i < n; ++i) {
1288 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1289 task_group.run(t->taskFunctor());
1292 for (
Integer i = 0; i < n; ++i) {
1293 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1311ARCANE_DI_REGISTER_PROVIDER(TBBTaskImplementation,
1312 DependencyInjection::ProviderProperty(
"TBBTaskImplementation"),
1313 ARCANE_DI_INTERFACES(ITaskImplementation),
1314 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.
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.
Informations d'exécution d'une boucle.
Interface d'un fonctor sur un interval d'itération multi-dimensionnel de dimension RankValue.
virtual void executeFunctor(const ComplexForLoopRanges< RankValue > &loop_range)=0
Exécute la méthode associée.
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.
virtual void executeFunctor(const TaskContext &tc)=0
Exécute la méthode associé
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.
void launchAndWait() override
Lance la tâche et bloque jusqu'à ce qu'elle se termine.
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.
Int32 maxThread() const
Nombre maximal de threads autorisés.
void setGrainSize(Integer v)
Positionne la taille (approximative) d'un intervalle d'itération.
@ Static
Utilise un partitionnement statique.
@ Deterministic
Utilise un partitionnement et un ordonnancement statique.
static bool hasProfiling()
Indique si le profilage est actif.
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 1D.
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 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.
bool isActive() const final
Indique si l'implémentation est active.
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 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[.
std::int32_t Int32
Type entier signé sur 32 bits.