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) {
137 ProfilingRegistry::_threadLocalForLoopInstance()->merge(*m_stat_info_ptr, m_run_info.traceInfo());
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>
355 class MDParallelForExecute;
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;
419 void initialize(
Int32 nb_thread)
override;
420 void terminate()
override;
440 _executeMDParallelFor<1>(loop_ranges, functor, run_info);
446 _executeMDParallelFor<2>(loop_ranges, functor, run_info);
452 _executeMDParallelFor<3>(loop_ranges, functor, run_info);
458 _executeMDParallelFor<4>(loop_ranges, functor, run_info);
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();
534 Impl(
Int32 nb_thread)
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;
552 std::atomic<Int32> m_nb_observed = 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();
590 std::scoped_lock sl(m_thread_created_mutex);
591 if (m_constructed_thread_map.contains(my_thread_id))
593 m_constructed_thread_map.insert(my_thread_id);
596 Int32 nb_observed = ++m_nb_observed;
600 std::ostringstream ostr;
601 ostr <<
"TBB: CREATE THREAD"
602 <<
" nb_allowed=" << m_nb_allowed_thread
603 <<
" tbb_default_allowed=" << tbb::info::default_concurrency()
604 <<
" id=" << my_thread_id
605 <<
" arena_id=" << _currentTaskTreadIndex()
606 <<
" is_worker=" << is_worker
607 <<
" nb_observed=" << nb_observed
609 std::cout << ostr.str();
611 TaskFactoryInternal::notifyThreadCreated();
615 void notifyThreadDestroyed([[maybe_unused]]
bool is_worker)
625#if TBB_VERSION_MAJOR > 2021 || (TBB_VERSION_MAJOR == 2021 && TBB_VERSION_MINOR > 5)
626 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = oneapi::tbb::attach();
628 oneapi::tbb::task_scheduler_handle m_task_scheduler_handle = tbb::task_scheduler_handle::get();
633 tbb::task_arena m_main_arena;
639 TaskObserver m_task_observer;
640 std::mutex m_thread_created_mutex;
641 std::vector<TaskThreadInfo> m_thread_task_infos;
642 std::unordered_set<std::thread::id> m_constructed_thread_map;
643 std::atomic<Int32> m_is_terminate_called = 0;
649 ConcurrencyBase::_setMaxAllowedThread(m_nb_allowed_thread);
652 std::cout <<
"TBB: TBBTaskImplementationInit nb_allowed_thread=" << m_nb_allowed_thread
653 <<
" id=" << std::this_thread::get_id()
654 <<
" version=" << TBB_VERSION_MAJOR <<
"." << TBB_VERSION_MINOR
657 m_thread_task_infos.resize(m_nb_allowed_thread);
658 m_task_observer.observe(
true);
659 Integer max_arena_size = m_nb_allowed_thread;
662 if (max_arena_size > 512)
663 max_arena_size = 512;
664 if (max_arena_size < 2)
668 for (
Integer i = 2; i < max_arena_size; ++i)
685 , m_stat_info(stat_info)
686 , m_nb_allowed_thread(nb_allowed_thread)
691 void operator()(tbb::blocked_range<Integer>& range)
const
695 std::ostringstream o;
697 <<
" id=" << std::this_thread::get_id()
698 <<
" max_allowed=" << m_nb_allowed_thread
699 <<
" range_begin=" << range.begin() <<
" range_size=" << range.size()
701 std::cout << o.str();
705 int tbb_index = _currentTaskTreadIndex();
706 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
707 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
708 tbb_index, m_nb_allowed_thread);
712 m_stat_info->incrementNbChunk();
713 m_functor->executeFunctor(range.begin(), CheckedConvert::toInteger(range.size()));
720 Int32 m_nb_allowed_thread;
729template <
int RankValue>
730class TBBMDParallelFor
736 , m_stat_info(stat_info)
737 , m_nb_allowed_thread(nb_allowed_thread)
742 void operator()(blocked_nd_range<Int32, RankValue>& range)
const
746 std::ostringstream o;
748 <<
" id=" << std::this_thread::get_id()
749 <<
" max_allowed=" << m_nb_allowed_thread
751 for (
Int32 i = 0; i < RankValue; ++i) {
752 auto r0 =
static_cast<Int32>(range.dim(i).begin());
753 auto r1 =
static_cast<Int32>(range.dim(i).size());
754 o <<
" range" << i <<
" (begin=" << r0 <<
" size=" << r1 <<
")";
757 std::cout << o.str();
761 int tbb_index = _currentTaskTreadIndex();
762 if (tbb_index < 0 || tbb_index >= m_nb_allowed_thread)
763 ARCCORE_FATAL(
"Invalid index for thread idx={0} valid_interval=[0..{1}[",
764 tbb_index, m_nb_allowed_thread);
768 m_stat_info->incrementNbChunk();
769 m_functor->executeFunctor(_fromTBBRange(range));
776 Int32 m_nb_allowed_thread;
800class TBBDeterministicParallelFor
808 , m_nb_thread(nb_thread)
809 , m_begin_index(begin_index)
811 , m_grain_size(grain_size)
814 , m_nb_block_per_thread(0)
819 if (m_grain_size > 0) {
820 m_block_size = m_grain_size;
821 if (m_block_size > 0) {
822 m_nb_block = m_size / m_block_size;
823 if ((m_size % m_block_size) != 0)
828 m_nb_block_per_thread = m_nb_block / m_nb_thread;
829 if ((m_nb_block % m_nb_thread) != 0)
830 ++m_nb_block_per_thread;
834 m_nb_block = m_nb_thread;
835 m_block_size = m_size / m_nb_block;
836 m_nb_block_per_thread = 1;
839 std::cout <<
"TBBDeterministicParallelFor: BEGIN=" << m_begin_index <<
" size=" << m_size
840 <<
" grain_size=" << m_grain_size
841 <<
" nb_block=" << m_nb_block <<
" nb_thread=" << m_nb_thread
842 <<
" nb_block_per_thread=" << m_nb_block_per_thread
843 <<
" block_size=" << m_block_size
844 <<
" block_size*nb_block=" << m_block_size * m_nb_block <<
'\n';
858 auto nb_iter =
static_cast<Integer>(range.size());
859 for (
Integer i = 0; i < nb_iter; ++i) {
860 Integer task_id = range.begin() + i;
861 for (
Integer k = 0, kn = m_nb_block_per_thread; k < kn; ++k) {
862 Integer block_id = task_id + (k * m_nb_thread);
863 if (block_id < m_nb_block)
864 _doBlock(task_id, block_id);
873 Integer iter_begin = block_id * m_block_size;
874 Integer iter_size = m_block_size;
875 if ((block_id + 1) == m_nb_block) {
877 iter_size = m_size - iter_begin;
879 iter_begin += m_begin_index;
881 if (TaskFactory::verboseLevel() >= 3) {
882 std::ostringstream o;
883 o <<
"TBB: DoBlock: BLOCK task_id=" << task_id <<
" block_id=" << block_id
884 <<
" iter_begin=" << iter_begin <<
" iter_size=" << iter_size <<
'\n';
885 std::cout << o.str();
890 auto r = tbb::blocked_range<int>(iter_begin, iter_begin + iter_size);
897 TBBTaskImplementation* m_impl;
898 const TBBParallelFor& m_tbb_for;
922 , m_stat_info(stat_info)
927 void operator()()
const
929 Integer nb_thread = m_options.maxThread();
931 Integer gsize = m_options.grainSize();
932 tbb::blocked_range<Integer> range(m_begin, m_begin + m_size);
934 std::cout <<
"TBB: TBBTaskImplementationInit ParallelForExecute begin=" << m_begin
935 <<
" size=" << m_size <<
" gsize=" << gsize
936 <<
" partitioner=" << (int)m_options.partitioner()
937 <<
" nb_thread=" << nb_thread
938 <<
" has_stat_info=" << (m_stat_info !=
nullptr)
942 range = tbb::blocked_range<Integer>(m_begin, m_begin + m_size, gsize);
945 tbb::parallel_for(range, pf, tbb::static_partitioner());
948 tbb::blocked_range<Integer> range2(0, nb_thread, 1);
950 tbb::parallel_for(range2, dpf);
953 tbb::parallel_for(range, pf);
958 TBBTaskImplementation* m_impl =
nullptr;
969template <
int RankValue>
970class TBBTaskImplementation::MDParallelForExecute
974 MDParallelForExecute(TBBTaskImplementation* impl,
979 , m_tbb_range(_toTBBRange(range))
982 , m_stat_info(stat_info)
987 Int32 gsize = m_options.grainSize();
993 constexpr bool is_verbose =
false;
994 std::array<Int32, RankValue> range_extents = range.extents().asStdArray();
995 double ratio =
static_cast<double>(gsize) /
static_cast<double>(range.nbElement());
996 if constexpr (is_verbose) {
997 std::cout <<
"GSIZE=" << gsize <<
" rank=" << RankValue <<
" ratio=" << ratio;
998 for (
Int32 i = 0; i < RankValue; ++i)
999 std::cout <<
" range" << i <<
"=" << range_extents[i];
1002 Int32 index = RankValue - 1;
1003 Int32 remaining_grain = gsize;
1004 for (; index >= 0; --index) {
1005 Int32 current = range_extents[index];
1006 if constexpr (is_verbose)
1007 std::cout <<
"Check index=" << index <<
" remaining=" << remaining_grain <<
" current=" << current <<
"\n";
1008 if (remaining_grain > current) {
1009 all_grain_sizes[index] = current;
1010 remaining_grain /= current;
1013 all_grain_sizes[index] = remaining_grain;
1017 for (Int32 i = 0; i < index; ++i)
1018 all_grain_sizes[i] = 1;
1019 if constexpr (is_verbose) {
1020 for (Int32 i = 0; i < RankValue; ++i)
1021 std::cout <<
" grain" << i <<
"=" << all_grain_sizes[i];
1024 m_tbb_range = _toTBBRangeWithGrain(m_tbb_range, all_grain_sizes);
1030 void operator()()
const
1032 Integer nb_thread = m_options.maxThread();
1033 TBBMDParallelFor<RankValue> pf(m_functor, nb_thread, m_stat_info);
1035 if (m_options.partitioner() == ParallelLoopOptions::Partitioner::Static) {
1036 tbb::parallel_for(m_tbb_range, pf, tbb::static_partitioner());
1038 else if (m_options.partitioner() == ParallelLoopOptions::Partitioner::Deterministic) {
1040 ARCCORE_THROW(NotImplementedException,
"ParallelLoopOptions::Partitioner::Deterministic for multi-dimensionnal loops");
1046 tbb::parallel_for(m_tbb_range, pf);
1052 TBBTaskImplementation* m_impl =
nullptr;
1053 blocked_nd_range<Int32, RankValue> m_tbb_range;
1054 IMDRangeFunctor<RankValue>* m_functor =
nullptr;
1055 ParallelLoopOptions m_options;
1056 ForLoopOneExecStat* m_stat_info =
nullptr;
1062TBBTaskImplementation::
1063~TBBTaskImplementation()
1072void TBBTaskImplementation::
1073initialize(
Int32 nb_thread)
1077 m_is_active = (nb_thread != 1);
1079 m_p =
new Impl(nb_thread);
1090void TBBTaskImplementation::
1102 o <<
"OneTBBTaskImplementation"
1103 <<
" version=" << TBB_VERSION_STRING
1104 <<
" interface=" << TBB_INTERFACE_VERSION
1105 <<
" runtime_interface=" << TBB_runtime_interface_version();
1111void TBBTaskImplementation::
1114 ScopedExecInfo sei(loop_info.runInfo());
1118 Int32 begin = loop_info.beginIndex();
1119 Int32 size = loop_info.size();
1125 Integer nb_allowed_thread = m_p->nbAllowedThread();
1127 max_thread = nb_allowed_thread;
1130 std::cout <<
"TBB: TBBTaskImplementation executeParallelFor begin=" << begin
1131 <<
" size=" << size <<
" max_thread=" << max_thread
1132 <<
" grain_size=" << options.
grainSize()
1133 <<
" nb_allowed=" << nb_allowed_thread <<
'\n';
1136 if (max_thread == 1 || max_thread == 0) {
1142 ParallelLoopOptions true_options(options);
1144 true_options.setMaxThread(max_thread);
1146 ParallelForExecute pfe(
this, true_options, begin, size, f, stat_info);
1148 tbb::task_arena* used_arena =
nullptr;
1149 if (max_thread < nb_allowed_thread && max_thread < m_p->m_sub_arena_list.size())
1152 used_arena = &(m_p->m_main_arena);
1153 used_arena->execute(pfe);
1162 _executeParallelFor(loop_info);
1174template <
int RankValue>
void TBBTaskImplementation::
1180 if (run_info.options().has_value())
1181 options = run_info.options().value();
1183 ScopedExecInfo sei(run_info);
1188 std::cout <<
"TBB: TBBTaskImplementation executeMDParallelFor nb_dim=" << RankValue
1189 <<
" nb_element=" << loop_ranges.nbElement()
1190 <<
" grain_size=" << options.
grainSize()
1191 <<
" name=" << run_info.traceInfo().traceInfo()
1192 <<
" has_stat_info=" << (stat_info !=
nullptr)
1198 if (max_thread == 1 || max_thread == 0) {
1204 ParallelLoopOptions true_options(options);
1207 Integer nb_allowed_thread = m_p->nbAllowedThread();
1209 max_thread = nb_allowed_thread;
1210 tbb::task_arena* used_arena =
nullptr;
1211 if (max_thread < nb_allowed_thread)
1212 used_arena = m_p->m_sub_arena_list[max_thread];
1214 used_arena = &(m_p->m_main_arena);
1217 if constexpr (RankValue == 1) {
1218 auto range_1d = _toTBBRange(loop_ranges);
1223 LambdaRangeFunctorT<
decltype(x1)> functor_1d(x1);
1224 Integer begin1 = CheckedConvert::toInteger(range_1d.dim(0).begin());
1225 Integer size1 = CheckedConvert::toInteger(range_1d.dim(0).size());
1227 used_arena->execute(pfe);
1230 MDParallelForExecute<RankValue> pfe(
this, true_options, loop_ranges, functor, stat_info);
1231 used_arena->execute(pfe);
1264 return m_p->threadTaskInfo(thread_id);
1277 if (thread_id < 0 || thread_id >= m_p->nbAllowedThread())
1281 Int32 task_index = tti->taskIndex();
1282 if (task_index >= 0)
1294 tbb::task_group task_group;
1295 task_group.run(taskFunctor());
1306 tbb::task_group task_group;
1312 for (
Integer i = 0; i < n; ++i) {
1313 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1314 task_group.run(t->taskFunctor());
1317 for (
Integer i = 0; i < n; ++i) {
1318 auto* t =
static_cast<OneTBBTask*
>(tasks[i]);
1329 if (m_task_group.isNull()) {
1330 m_task_group =
makeRef(
new tbb::task_group());
1332 m_task_group->run(taskFunctor());
1341 if (m_task_group.isNull()) {
1344 m_task_group->wait();
1361ARCANE_DI_REGISTER_PROVIDER(TBBTaskImplementation,
1362 DependencyInjection::ProviderProperty(
"TBBTaskImplementation"),
1363 ARCANE_DI_INTERFACES(ITaskImplementation),
1364 ARCANE_DI_EMPTY_CONSTRUCTOR());
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_THROW(exception_class,...)
Macro to throw an exception with formatting.
#define ARCCORE_CHECK_POINTER(ptr)
Macro that returns the pointer ptr if it is not null or throws an exception if it is null.
Represents the bounds of a multidimensional array.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Class to manage the profiling of a single loop execution.
Loop execution information.
Interface of a functor on a multi-dimensional iteration interval of dimension RankValue.
virtual void executeFunctor(const ComplexForLoopRanges< RankValue > &loop_range)=0
Executes the associated method.
Interface of a functor on an iteration interval.
virtual void executeFunctor(Int32 begin, Int32 size)=0
Executes the associated method.
virtual void executeFunctor(const TaskContext &tc)=0
Executes the associated method.
Int32 nbAllowedThread() const
Maximum number of threads used to manage tasks.
Interface for a concurrent task.
Class allowing retrieval of the time spent between the constructor call and the destructor call.
void wait() override
Method allowing to wait the end of the task.
void launchAndWait() override
Launches the task and blocks until it finishes.
void launch() override
Method allowing to launch the task.
Characteristics of a multi-thread 1D loop.
Execution options for a parallel loop in multi-threading.
Integer grainSize() const
Size of an iteration interval.
Int32 maxThread() const
Maximum number of allowed threads.
void setGrainSize(Integer v)
Sets the size (approximate) of an iteration interval.
@ Static
Uses static partitioning.
@ Deterministic
Uses static partitioning and scheduling.
static bool hasProfiling()
Indicates if profiling is active.
Reference to an instance.
Deterministic implementation of ParallelFor.
void operator()(tbb::blocked_range< Integer > &range) const
Operator for a given thread.
std::vector< tbb::task_arena * > m_sub_arena_list
Array whose i-th element contains the tbb::task_arena for i thread.
Class for positioning TaskThreadInfo::taskIndex().
Int32 currentTaskThreadIndex() const final
Implementation of TaskFactory::currentTaskThreadIndex().
void executeParallelFor(const ComplexForLoopRanges< 1 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 1 > *functor) final
Executes a 1D loop in parallel.
void executeParallelFor(Int32 begin, Int32 size, IRangeFunctor *f) final
Executes the functor f in parallel.
ITask * createRootTask(ITaskFunctor *f) override
Creates a root task. The implementation must copy the value of f, which is either a TaskFunctor or a ...
void printInfos(std::ostream &o) const final
Prints information about the runtime used.
void executeParallelFor(Int32 begin, Int32 size, const ParallelLoopOptions &options, IRangeFunctor *f) final
Executes the functor f in parallel.
void executeParallelFor(const ComplexForLoopRanges< 3 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 3 > *functor) final
Executes a 3D loop in parallel.
void executeParallelFor(const ComplexForLoopRanges< 4 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 4 > *functor) final
Executes a 4D loop in parallel.
TaskThreadInfo * currentTaskThreadInfo() const
Instance of TaskThreadInfo associated with the current thread.
bool isActive() const final
Indicates if the implementation is active.
Int32 currentTaskIndex() const final
Implementation of TaskFactory::currentTaskIndex().
void executeParallelFor(const ComplexForLoopRanges< 2 > &loop_ranges, const ForLoopRunInfo &run_info, IMDRangeFunctor< 2 > *functor) final
Executes a 2D loop in parallel.
Execution context of a task.
static const ParallelLoopOptions & defaultParallelLoopOptions()
Default parallel loop execution options.
static Integer verboseLevel()
Verbosity level.
static void setDefaultParallelLoopOptions(const ParallelLoopOptions &v)
Sets the default parallel loop execution options.
static Int32 currentTaskThreadIndex()
Index (between 0 and nbAllowedThread()-1) of the thread executing the current task.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
SimpleForLoopRanges< 1 > makeLoopRanges(Int32 n1)
Creates an iteration range [0,n1[, [0,n2[.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.