21 #include "kmp_error.h"
24 #include "kmp_stats.h"
26 #if KMP_USE_X87CONTROL
30 #include "kmp_dispatch.h"
31 #if KMP_USE_HIER_SCHED
32 #include "kmp_dispatch_hier.h"
36 #include "ompt-specific.h"
42 void __kmp_dispatch_deo_error(
int *gtid_ref,
int *cid_ref,
ident_t *loc_ref) {
45 KMP_DEBUG_ASSERT(gtid_ref);
47 if (__kmp_env_consistency_check) {
48 th = __kmp_threads[*gtid_ref];
49 if (th->th.th_root->r.r_active &&
50 (th->th.th_dispatch->th_dispatch_pr_current->pushed_ws != ct_none)) {
51 #if KMP_USE_DYNAMIC_LOCK
52 __kmp_push_sync(*gtid_ref, ct_ordered_in_pdo, loc_ref, NULL, 0);
54 __kmp_push_sync(*gtid_ref, ct_ordered_in_pdo, loc_ref, NULL);
60 void __kmp_dispatch_dxo_error(
int *gtid_ref,
int *cid_ref,
ident_t *loc_ref) {
63 if (__kmp_env_consistency_check) {
64 th = __kmp_threads[*gtid_ref];
65 if (th->th.th_dispatch->th_dispatch_pr_current->pushed_ws != ct_none) {
66 __kmp_pop_sync(*gtid_ref, ct_ordered_in_pdo, loc_ref);
73 bool use_hier =
false) {
76 int monotonicity = SCHEDULE_NONMONOTONIC;
80 if (loc != NULL && loc->get_openmp_version() < 50)
81 monotonicity = SCHEDULE_MONOTONIC;
83 if (use_hier || __kmp_force_monotonic)
84 monotonicity = SCHEDULE_MONOTONIC;
85 else if (SCHEDULE_HAS_NONMONOTONIC(schedule))
86 monotonicity = SCHEDULE_NONMONOTONIC;
87 else if (SCHEDULE_HAS_MONOTONIC(schedule))
88 monotonicity = SCHEDULE_MONOTONIC;
93 #if KMP_STATIC_STEAL_ENABLED
119 template <
typename T>
120 void __kmp_dispatch_init_algorithm(
ident_t *loc,
int gtid,
121 dispatch_private_info_template<T> *pr,
123 typename traits_t<T>::signed_t st,
125 kmp_uint64 *cur_chunk,
127 typename traits_t<T>::signed_t chunk,
129 typedef typename traits_t<T>::unsigned_t UT;
130 typedef typename traits_t<T>::floating_t DBL;
140 typedef typename traits_t<T>::signed_t ST;
144 buff = __kmp_str_format(
"__kmp_dispatch_init_algorithm: T#%%d called "
145 "pr:%%p lb:%%%s ub:%%%s st:%%%s "
146 "schedule:%%d chunk:%%%s nproc:%%%s tid:%%%s\n",
147 traits_t<T>::spec, traits_t<T>::spec,
148 traits_t<ST>::spec, traits_t<ST>::spec,
149 traits_t<T>::spec, traits_t<T>::spec);
150 KD_TRACE(10, (buff, gtid, pr, lb, ub, st, schedule, chunk, nproc, tid));
151 __kmp_str_free(&buff);
155 th = __kmp_threads[gtid];
156 team = th->th.th_team;
157 active = !team->t.t_serialized;
160 int itt_need_metadata_reporting =
161 __itt_metadata_add_ptr && __kmp_forkjoin_frames_mode == 3 &&
162 KMP_MASTER_GTID(gtid) && th->th.th_teams_microtask == NULL &&
163 team->t.t_active_level == 1;
166 #if KMP_USE_HIER_SCHED
167 use_hier = pr->flags.use_hier;
173 monotonicity = __kmp_get_monotonicity(loc, schedule, use_hier);
174 schedule = SCHEDULE_WITHOUT_MODIFIERS(schedule);
178 pr->flags.nomerge = TRUE;
182 pr->flags.nomerge = FALSE;
184 pr->type_size = traits_t<T>::type_size;
186 pr->flags.ordered = TRUE;
190 pr->flags.ordered = FALSE;
193 if (pr->flags.ordered) {
194 monotonicity = SCHEDULE_MONOTONIC;
198 schedule = __kmp_static;
200 if (schedule == kmp_sch_runtime) {
203 schedule = team->t.t_sched.r_sched_type;
204 monotonicity = __kmp_get_monotonicity(loc, schedule, use_hier);
205 schedule = SCHEDULE_WITHOUT_MODIFIERS(schedule);
206 if (pr->flags.ordered)
207 monotonicity = SCHEDULE_MONOTONIC;
211 schedule = __kmp_guided;
213 schedule = __kmp_static;
217 chunk = team->t.t_sched.chunk;
226 buff = __kmp_str_format(
"__kmp_dispatch_init_algorithm: T#%%d new: "
227 "schedule:%%d chunk:%%%s\n",
229 KD_TRACE(10, (buff, gtid, schedule, chunk));
230 __kmp_str_free(&buff);
235 schedule = __kmp_guided;
238 chunk = KMP_DEFAULT_CHUNK;
244 schedule = __kmp_auto;
249 buff = __kmp_str_format(
250 "__kmp_dispatch_init_algorithm: kmp_sch_auto: T#%%d new: "
251 "schedule:%%d chunk:%%%s\n",
253 KD_TRACE(10, (buff, gtid, schedule, chunk));
254 __kmp_str_free(&buff);
258 #if KMP_STATIC_STEAL_ENABLED
260 if (schedule == kmp_sch_dynamic_chunked) {
261 if (monotonicity == SCHEDULE_NONMONOTONIC)
262 schedule = kmp_sch_static_steal;
266 if (schedule == kmp_sch_guided_analytical_chunked && nproc > 1 << 20) {
267 schedule = kmp_sch_guided_iterative_chunked;
268 KMP_WARNING(DispatchManyThreads);
272 schedule = team->t.t_sched.r_sched_type;
273 monotonicity = __kmp_get_monotonicity(loc, schedule, use_hier);
274 schedule = SCHEDULE_WITHOUT_MODIFIERS(schedule);
278 schedule == __kmp_static) {
279 schedule = kmp_sch_static_balanced_chunked;
284 chunk = team->t.t_sched.chunk * chunk;
294 buff = __kmp_str_format(
295 "__kmp_dispatch_init_algorithm: T#%%d new: schedule:%%d"
298 KD_TRACE(10, (buff, gtid, schedule, chunk));
299 __kmp_str_free(&buff);
303 pr->u.p.parm1 = chunk;
306 "unknown scheduling type");
310 if (__kmp_env_consistency_check) {
312 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited,
313 (pr->flags.ordered ? ct_pdo_ordered : ct_pdo), loc);
327 tc = (UT)(lb - ub) / (-st) + 1;
335 tc = (UT)(ub - lb) / st + 1;
341 #if KMP_STATS_ENABLED
342 if (KMP_MASTER_GTID(gtid)) {
353 pr->u.p.last_upper = ub + st;
359 if (pr->flags.ordered) {
360 pr->ordered_bumped = 0;
361 pr->u.p.ordered_lower = 1;
362 pr->u.p.ordered_upper = 0;
367 #if KMP_STATIC_STEAL_ENABLED
368 case kmp_sch_static_steal: {
372 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_static_steal case\n",
375 ntc = (tc % chunk ? 1 : 0) + tc / chunk;
376 if (nproc > 1 && ntc >= nproc) {
379 T small_chunk, extras;
380 kmp_uint32 old = UNUSED;
381 int claimed = pr->steal_flag.compare_exchange_strong(old, CLAIMED);
382 if (traits_t<T>::type_size > 4) {
388 pr->u.p.steal_lock = (kmp_lock_t *)__kmp_allocate(
sizeof(kmp_lock_t));
389 __kmp_init_lock(pr->u.p.steal_lock);
391 small_chunk = ntc / nproc;
392 extras = ntc % nproc;
394 init =
id * small_chunk + (
id < extras ? id : extras);
395 pr->u.p.count = init;
397 pr->u.p.ub = init + small_chunk + (
id < extras ? 1 : 0);
400 KMP_ATOMIC_ST_REL(&pr->steal_flag, READY);
403 KMP_DEBUG_ASSERT(pr->steal_flag == THIEF);
409 pr->u.p.parm3 = nproc;
410 pr->u.p.parm4 = (
id + 1) % nproc;
414 schedule = kmp_sch_dynamic_chunked;
415 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d switching to "
416 "kmp_sch_dynamic_chunked\n",
423 case kmp_sch_static_balanced: {
428 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_static_balanced case\n",
438 pr->u.p.parm1 = (
id == tc - 1);
441 pr->u.p.parm1 = FALSE;
445 T small_chunk = tc / nproc;
446 T extras = tc % nproc;
447 init =
id * small_chunk + (
id < extras ? id : extras);
448 limit = init + small_chunk - (
id < extras ? 0 : 1);
449 pr->u.p.parm1 = (
id == nproc - 1);
455 pr->u.p.parm1 = TRUE;
459 pr->u.p.parm1 = FALSE;
465 if (itt_need_metadata_reporting)
467 *cur_chunk = limit - init + 1;
470 pr->u.p.lb = lb + init;
471 pr->u.p.ub = lb + limit;
474 T ub_tmp = lb + limit * st;
475 pr->u.p.lb = lb + init * st;
479 pr->u.p.ub = (ub_tmp + st > ub ? ub : ub_tmp);
481 pr->u.p.ub = (ub_tmp + st < ub ? ub : ub_tmp);
484 if (pr->flags.ordered) {
485 pr->u.p.ordered_lower = init;
486 pr->u.p.ordered_upper = limit;
490 case kmp_sch_static_balanced_chunked: {
493 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d runtime(simd:static)"
494 " -> falling-through to static_greedy\n",
496 schedule = kmp_sch_static_greedy;
498 pr->u.p.parm1 = ((tc + nth - 1) / nth + chunk - 1) & ~(chunk - 1);
504 case kmp_sch_guided_iterative_chunked: {
507 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_guided_iterative_chunked"
512 if ((2L * chunk + 1) * nproc >= tc) {
514 schedule = kmp_sch_dynamic_chunked;
518 pr->u.p.parm2 = guided_int_param * nproc * (chunk + 1);
519 *(
double *)&pr->u.p.parm3 =
520 guided_flt_param / (
double)nproc;
523 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d falling-through to "
524 "kmp_sch_static_greedy\n",
526 schedule = kmp_sch_static_greedy;
530 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_static_greedy case\n",
536 case kmp_sch_guided_analytical_chunked: {
537 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d "
538 "kmp_sch_guided_analytical_chunked case\n",
542 if ((2L * chunk + 1) * nproc >= tc) {
544 schedule = kmp_sch_dynamic_chunked;
550 #if KMP_USE_X87CONTROL
560 unsigned int oldFpcw = _control87(0, 0);
561 _control87(_PC_64, _MCW_PC);
565 long double target = ((
long double)chunk * 2 + 1) * nproc / tc;
572 x = 1.0 - 0.5 / (double)nproc;
583 ptrdiff_t natural_alignment =
584 (ptrdiff_t)&t.b - (ptrdiff_t)&t - (ptrdiff_t)1;
588 (((ptrdiff_t)&pr->u.p.parm3) & (natural_alignment)) == 0);
593 *(DBL *)&pr->u.p.parm3 = x;
606 p = __kmp_pow<UT>(x, right);
611 }
while (p > target && right < (1 << 27));
619 while (left + 1 < right) {
620 mid = (left + right) / 2;
621 if (__kmp_pow<UT>(x, mid) > target) {
630 KMP_ASSERT(cross && __kmp_pow<UT>(x, cross - 1) > target &&
631 __kmp_pow<UT>(x, cross) <= target);
634 pr->u.p.parm2 = cross;
637 #if ((KMP_OS_LINUX || KMP_OS_WINDOWS) && KMP_ARCH_X86) && (!defined(KMP_I8))
638 #define GUIDED_ANALYTICAL_WORKAROUND (*(DBL *)&pr->u.p.parm3)
640 #define GUIDED_ANALYTICAL_WORKAROUND (x)
644 __kmp_dispatch_guided_remaining(
645 tc, GUIDED_ANALYTICAL_WORKAROUND, cross) -
647 #if KMP_USE_X87CONTROL
649 _control87(oldFpcw, _MCW_PC);
653 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d falling-through to "
654 "kmp_sch_static_greedy\n",
656 schedule = kmp_sch_static_greedy;
662 case kmp_sch_static_greedy:
665 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_static_greedy case\n",
667 pr->u.p.parm1 = (nproc > 1) ? (tc + nproc - 1) / nproc : tc;
669 case kmp_sch_static_chunked:
670 case kmp_sch_dynamic_chunked:
674 if (pr->u.p.parm1 <= 0)
675 pr->u.p.parm1 = KMP_DEFAULT_CHUNK;
676 else if (pr->u.p.parm1 > tc)
680 pr->u.p.parm2 = (tc / pr->u.p.parm1) + (tc % pr->u.p.parm1 ? 1 : 0);
681 KD_TRACE(100, (
"__kmp_dispatch_init_algorithm: T#%d "
682 "kmp_sch_static_chunked/kmp_sch_dynamic_chunked cases\n",
685 case kmp_sch_trapezoidal: {
688 T parm1, parm2, parm3, parm4;
690 (
"__kmp_dispatch_init_algorithm: T#%d kmp_sch_trapezoidal case\n",
696 parm2 = (tc / (2 * nproc));
706 }
else if (parm1 > parm2) {
711 parm3 = (parm2 + parm1);
712 parm3 = (2 * tc + parm3 - 1) / parm3;
720 parm4 = (parm2 - parm1) / parm4;
727 pr->u.p.parm1 = parm1;
728 pr->u.p.parm2 = parm2;
729 pr->u.p.parm3 = parm3;
730 pr->u.p.parm4 = parm4;
735 __kmp_fatal(KMP_MSG(UnknownSchedTypeDetected),
736 KMP_HNT(GetNewerLibrary),
741 pr->schedule = schedule;
744 #if KMP_USE_HIER_SCHED
745 template <
typename T>
746 inline void __kmp_dispatch_init_hier_runtime(
ident_t *loc, T lb, T ub,
747 typename traits_t<T>::signed_t st);
750 __kmp_dispatch_init_hier_runtime<kmp_int32>(
ident_t *loc, kmp_int32 lb,
751 kmp_int32 ub, kmp_int32 st) {
752 __kmp_dispatch_init_hierarchy<kmp_int32>(
753 loc, __kmp_hier_scheds.size, __kmp_hier_scheds.layers,
754 __kmp_hier_scheds.scheds, __kmp_hier_scheds.small_chunks, lb, ub, st);
758 __kmp_dispatch_init_hier_runtime<kmp_uint32>(
ident_t *loc, kmp_uint32 lb,
759 kmp_uint32 ub, kmp_int32 st) {
760 __kmp_dispatch_init_hierarchy<kmp_uint32>(
761 loc, __kmp_hier_scheds.size, __kmp_hier_scheds.layers,
762 __kmp_hier_scheds.scheds, __kmp_hier_scheds.small_chunks, lb, ub, st);
766 __kmp_dispatch_init_hier_runtime<kmp_int64>(
ident_t *loc, kmp_int64 lb,
767 kmp_int64 ub, kmp_int64 st) {
768 __kmp_dispatch_init_hierarchy<kmp_int64>(
769 loc, __kmp_hier_scheds.size, __kmp_hier_scheds.layers,
770 __kmp_hier_scheds.scheds, __kmp_hier_scheds.large_chunks, lb, ub, st);
774 __kmp_dispatch_init_hier_runtime<kmp_uint64>(
ident_t *loc, kmp_uint64 lb,
775 kmp_uint64 ub, kmp_int64 st) {
776 __kmp_dispatch_init_hierarchy<kmp_uint64>(
777 loc, __kmp_hier_scheds.size, __kmp_hier_scheds.layers,
778 __kmp_hier_scheds.scheds, __kmp_hier_scheds.large_chunks, lb, ub, st);
782 void __kmp_dispatch_free_hierarchies(kmp_team_t *team) {
783 int num_disp_buff = team->t.t_max_nproc > 1 ? __kmp_dispatch_num_buffers : 2;
784 for (
int i = 0; i < num_disp_buff; ++i) {
787 reinterpret_cast<dispatch_shared_info_template<kmp_int32>
volatile *
>(
788 &team->t.t_disp_buffer[i]);
790 sh->hier->deallocate();
791 __kmp_free(sh->hier);
799 template <
typename T>
802 T ub,
typename traits_t<T>::signed_t st,
803 typename traits_t<T>::signed_t chunk,
int push_ws) {
804 typedef typename traits_t<T>::unsigned_t UT;
809 kmp_uint32 my_buffer_index;
810 dispatch_private_info_template<T> *pr;
811 dispatch_shared_info_template<T>
volatile *sh;
813 KMP_BUILD_ASSERT(
sizeof(dispatch_private_info_template<T>) ==
814 sizeof(dispatch_private_info));
815 KMP_BUILD_ASSERT(
sizeof(dispatch_shared_info_template<UT>) ==
816 sizeof(dispatch_shared_info));
817 __kmp_assert_valid_gtid(gtid);
819 if (!TCR_4(__kmp_init_parallel))
820 __kmp_parallel_initialize();
822 __kmp_resume_if_soft_paused();
824 #if INCLUDE_SSC_MARKS
825 SSC_MARK_DISPATCH_INIT();
828 typedef typename traits_t<T>::signed_t ST;
832 buff = __kmp_str_format(
"__kmp_dispatch_init: T#%%d called: schedule:%%d "
833 "chunk:%%%s lb:%%%s ub:%%%s st:%%%s\n",
834 traits_t<ST>::spec, traits_t<T>::spec,
835 traits_t<T>::spec, traits_t<ST>::spec);
836 KD_TRACE(10, (buff, gtid, schedule, chunk, lb, ub, st));
837 __kmp_str_free(&buff);
841 th = __kmp_threads[gtid];
842 team = th->th.th_team;
843 active = !team->t.t_serialized;
844 th->th.th_ident = loc;
849 if (schedule == __kmp_static) {
855 #if KMP_USE_HIER_SCHED
861 my_buffer_index = th->th.th_dispatch->th_disp_index;
862 pr =
reinterpret_cast<dispatch_private_info_template<T> *
>(
864 ->th_disp_buffer[my_buffer_index % __kmp_dispatch_num_buffers]);
865 my_sched = SCHEDULE_WITHOUT_MODIFIERS(my_sched);