LLVM OpenMP* Runtime Library
Loading...
Searching...
No Matches
kmp_sched.cpp
1/*
2 * kmp_sched.cpp -- static scheduling -- iteration initialization
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13/* Static scheduling initialization.
14
15 NOTE: team->t.t_nproc is a constant inside of any dispatch loop, however
16 it may change values between parallel regions. __kmp_max_nth
17 is the largest value __kmp_nth may take, 1 is the smallest. */
18
19#include "kmp.h"
20#include "kmp_error.h"
21#include "kmp_i18n.h"
22#include "kmp_itt.h"
23#include "kmp_stats.h"
24#include "kmp_str.h"
25
26#if OMPT_SUPPORT
27#include "ompt-specific.h"
28#endif
29
30#ifdef KMP_DEBUG
31//-------------------------------------------------------------------------
32// template for debug prints specification ( d, u, lld, llu )
33char const *traits_t<int>::spec = "d";
34char const *traits_t<unsigned int>::spec = "u";
35char const *traits_t<long long>::spec = "lld";
36char const *traits_t<unsigned long long>::spec = "llu";
37char const *traits_t<long>::spec = "ld";
38//-------------------------------------------------------------------------
39#endif
40
41#if KMP_STATS_ENABLED
42#define KMP_STATS_LOOP_END(stat) \
43 { \
44 kmp_int64 t; \
45 kmp_int64 u = (kmp_int64)(*pupper); \
46 kmp_int64 l = (kmp_int64)(*plower); \
47 kmp_int64 i = (kmp_int64)incr; \
48 if (i == 1) { \
49 t = u - l + 1; \
50 } else if (i == -1) { \
51 t = l - u + 1; \
52 } else if (i > 0) { \
53 t = (u - l) / i + 1; \
54 } else { \
55 KMP_DEBUG_ASSERT(i != 0); \
56 t = (l - u) / (-i) + 1; \
57 } \
58 KMP_COUNT_VALUE(stat, t); \
59 KMP_POP_PARTITIONED_TIMER(); \
60 }
61#else
62#define KMP_STATS_LOOP_END(stat) /* Nothing */
63#endif
64
65#if USE_ITT_BUILD || defined KMP_DEBUG
66static ident_t loc_stub = {0, KMP_IDENT_KMPC, 0, 0, ";unknown;unknown;0;0;;"};
67static inline void check_loc(ident_t *&loc) {
68 if (loc == NULL)
69 loc = &loc_stub; // may need to report location info to ittnotify
70}
71#endif
72
73template <typename T>
74static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid,
75 kmp_int32 schedtype, kmp_int32 *plastiter,
76 T *plower, T *pupper,
77 typename traits_t<T>::signed_t *pstride,
78 typename traits_t<T>::signed_t incr,
79 typename traits_t<T>::signed_t chunk
80#if OMPT_SUPPORT && OMPT_OPTIONAL
81 ,
82 void *codeptr
83#endif
84) {
85 KMP_COUNT_BLOCK(OMP_LOOP_STATIC);
86 KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static);
87 KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static_scheduling);
88
89 // Clear monotonic/nonmonotonic bits (ignore it)
90 schedtype = SCHEDULE_WITHOUT_MODIFIERS(schedtype);
91
92 typedef typename traits_t<T>::unsigned_t UT;
93 typedef typename traits_t<T>::signed_t ST;
94 /* this all has to be changed back to TID and such.. */
95 kmp_int32 gtid = global_tid;
96 kmp_uint32 tid;
97 kmp_uint32 nth;
98 UT trip_count;
99 kmp_team_t *team;
100 __kmp_assert_valid_gtid(gtid);
101 kmp_info_t *th = __kmp_threads[gtid];
102
103#if OMPT_SUPPORT && OMPT_OPTIONAL
104 ompt_team_info_t *team_info = NULL;
105 ompt_task_info_t *task_info = NULL;
106 ompt_work_t ompt_work_type = ompt_work_loop_static;
107
108 static kmp_int8 warn = 0;
109
110 if (ompt_enabled.ompt_callback_work || ompt_enabled.ompt_callback_dispatch) {
111 // Only fully initialize variables needed by OMPT if OMPT is enabled.
112 team_info = __ompt_get_teaminfo(0, NULL);
113 task_info = __ompt_get_task_info_object(0);
114 // Determine workshare type
115 if (loc != NULL) {
116 if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) {
117 ompt_work_type = ompt_work_loop_static;
118 } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) {
119 ompt_work_type = ompt_work_sections;
120 } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) {
121 ompt_work_type = ompt_work_distribute;
122 } else {
123 kmp_int8 bool_res =
124 KMP_COMPARE_AND_STORE_ACQ8(&warn, (kmp_int8)0, (kmp_int8)1);
125 if (bool_res)
126 KMP_WARNING(OmptOutdatedWorkshare);
127 }
128 KMP_DEBUG_ASSERT(ompt_work_type);
129 }
130 }
131#define OMPT_LOOP_BEGIN(count) \
132 if (ompt_enabled.ompt_callback_work) { \
133 ompt_callbacks.ompt_callback(ompt_callback_work)( \
134 ompt_work_type, ompt_scope_begin, &(team_info->parallel_data), \
135 &(task_info->task_data), count, codeptr); \
136 }
137#else
138#define OMPT_LOOP_BEGIN(count) // no-op
139#endif
140
141 KMP_DEBUG_ASSERT(plastiter && plower && pupper && pstride);
142 KE_TRACE(10, ("__kmpc_for_static_init called (%d)\n", global_tid));
143#ifdef KMP_DEBUG
144 {
145 char *buff;
146 // create format specifiers before the debug output
147 buff = __kmp_str_format(
148 "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s,"
149 " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
150 traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
151 traits_t<ST>::spec, traits_t<ST>::spec, traits_t<T>::spec);
152 KD_TRACE(100, (buff, global_tid, schedtype, *plastiter, *plower, *pupper,
153 *pstride, incr, chunk));
154 __kmp_str_free(&buff);
155 }
156#endif
157
158 if (__kmp_env_consistency_check) {
159 __kmp_push_workshare(global_tid, ct_pdo, loc);
160 if (incr == 0) {
161 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
162 loc);
163 }
164 }
165 /* special handling for zero-trip loops */
166 if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
167 if (plastiter != NULL)
168 *plastiter = FALSE;
169 /* leave pupper and plower set to entire iteration space */
170 *pstride = incr; /* value should never be used */
171// *plower = *pupper - incr;
172// let compiler bypass the illegal loop (like for(i=1;i<10;i--))
173// THE LINE COMMENTED ABOVE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE
174// ON A ZERO-TRIP LOOP (lower=1, upper=0,stride=1) - JPH June 23, 2009.
175#ifdef KMP_DEBUG
176 {
177 char *buff;
178 // create format specifiers before the debug output
179 buff = __kmp_str_format("__kmpc_for_static_init:(ZERO TRIP) liter=%%d "
180 "lower=%%%s upper=%%%s stride = %%%s "
181 "signed?<%s>, loc = %%s\n",
182 traits_t<T>::spec, traits_t<T>::spec,
183 traits_t<ST>::spec, traits_t<T>::spec);
184 check_loc(loc);
185 KD_TRACE(100,
186 (buff, *plastiter, *plower, *pupper, *pstride, loc->psource));
187 __kmp_str_free(&buff);
188 }
189#endif
190 KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
191
192 OMPT_LOOP_BEGIN(0);
193 KMP_STATS_LOOP_END(OMP_loop_static_iterations);
194 return;
195 }
196
197 // Although there are schedule enumerations above kmp_ord_upper which are not
198 // schedules for "distribute", the only ones which are useful are dynamic, so
199 // cannot be seen here, since this codepath is only executed for static
200 // schedules.
201 if (schedtype > kmp_ord_upper) {
202 // we are in DISTRIBUTE construct
203 schedtype += kmp_sch_static -
204 kmp_distribute_static; // AC: convert to usual schedule type
205 if (th->th.th_team->t.t_serialized > 1) {
206 tid = 0;
207 team = th->th.th_team;
208 } else {
209 tid = th->th.th_team->t.t_master_tid;
210 team = th->th.th_team->t.t_parent;
211 }
212 } else {
213 tid = __kmp_tid_from_gtid(global_tid);
214 team = th->th.th_team;
215 }
216
217 /* determine if "for" loop is an active worksharing construct */
218 if (team->t.t_serialized) {
219 /* serialized parallel, each thread executes whole iteration space */
220 if (plastiter != NULL)
221 *plastiter = TRUE;
222 /* leave pupper and plower set to entire iteration space */
223 *pstride =
224 (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
225
226#ifdef KMP_DEBUG
227 {
228 char *buff;
229 // create format specifiers before the debug output
230 buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
231 "lower=%%%s upper=%%%s stride = %%%s\n",
232 traits_t<T>::spec, traits_t<T>::spec,
233 traits_t<ST>::spec);
234 KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
235 __kmp_str_free(&buff);
236 }
237#endif
238 KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
239
240 OMPT_LOOP_BEGIN(*pstride);
241 KMP_STATS_LOOP_END(OMP_loop_static_iterations);
242 return;
243 }
244 nth = team->t.t_nproc;
245 if (nth == 1) {
246 if (plastiter != NULL)
247 *plastiter = TRUE;
248 *pstride =
249 (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
250#ifdef KMP_DEBUG
251 {
252 char *buff;
253 // create format specifiers before the debug output
254 buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
255 "lower=%%%s upper=%%%s stride = %%%s\n",
256 traits_t<T>::spec, traits_t<T>::spec,
257 traits_t<ST>::spec);
258 KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
259 __kmp_str_free(&buff);
260 }
261#endif
262 KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
263
264 OMPT_LOOP_BEGIN(*pstride);
265 KMP_STATS_LOOP_END(OMP_loop_static_iterations);
266 return;
267 }
268
269 /* compute trip count */
270 if (incr == 1) {
271 trip_count = *pupper - *plower + 1;
272 } else if (incr == -1) {
273 trip_count = *plower - *pupper + 1;
274 } else if (incr > 0) {
275 // upper-lower can exceed the limit of signed type
276 trip_count = (UT)(*pupper - *plower) / incr + 1;
277 } else {
278 KMP_DEBUG_ASSERT(incr != 0);
279 trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
280 }
281
282#if KMP_STATS_ENABLED
283 if (KMP_MASTER_GTID(gtid)) {
284 KMP_COUNT_VALUE(OMP_loop_static_total_iterations, trip_count);
285 }
286#endif
287
288 if (__kmp_env_consistency_check) {
289 /* tripcount overflow? */
290 if (trip_count == 0 && *pupper != *plower) {
291 __kmp_error_construct(kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo,
292 loc);
293 }
294 }
295
296 /* compute remaining parameters */
297 switch (schedtype) {
298 case kmp_sch_static: {
299 if (trip_count < nth) {
300 KMP_DEBUG_ASSERT(
301 __kmp_static == kmp_sch_static_greedy ||
302 __kmp_static ==
303 kmp_sch_static_balanced); // Unknown static scheduling type.
304 if (tid < trip_count) {
305 *pupper = *plower = *plower + tid * incr;
306 } else {
307 // set bounds so non-active threads execute no iterations
308 *plower = *pupper + (incr > 0 ? 1 : -1);
309 }
310 if (plastiter != NULL)
311 *plastiter = (tid == trip_count - 1);
312 } else {
313 KMP_DEBUG_ASSERT(nth != 0);
314 if (__kmp_static == kmp_sch_static_balanced) {
315 UT small_chunk = trip_count / nth;
316 UT extras = trip_count % nth;
317 *plower += incr * (tid * small_chunk + (tid < extras ? tid : extras));
318 *pupper = *plower + small_chunk * incr - (tid < extras ? 0 : incr);
319 if (plastiter != NULL)
320 *plastiter = (tid == nth - 1);
321 } else {
322 T big_chunk_inc_count =
323 (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
324 T old_upper = *pupper;
325
326 KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
327 // Unknown static scheduling type.
328
329 *plower += tid * big_chunk_inc_count;
330 *pupper = *plower + big_chunk_inc_count - incr;
331 if (incr > 0) {
332 if (*pupper < *plower)
333 *pupper = traits_t<T>::max_value;
334 if (plastiter != NULL)
335 *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
336 if (*pupper > old_upper)
337 *pupper = old_upper; // tracker C73258
338 } else {
339 if (*pupper > *plower)
340 *pupper = traits_t<T>::min_value;
341 if (plastiter != NULL)
342 *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
343 if (*pupper < old_upper)
344 *pupper = old_upper; // tracker C73258
345 }
346 }
347 }
348 *pstride = trip_count;
349 break;
350 }
351 case kmp_sch_static_chunked: {
352 ST span;
353 UT nchunks;
354 KMP_DEBUG_ASSERT(chunk != 0);
355 if (chunk < 1)
356 chunk = 1;
357 else if ((UT)chunk > trip_count)
358 chunk = trip_count;
359 nchunks = (trip_count) / (UT)chunk + (trip_count % (UT)chunk ? 1 : 0);
360 span = chunk * incr;
361 if (nchunks < nth) {
362 *pstride = span * nchunks;
363 if (tid < nchunks) {
364 *plower = *plower + (span * tid);
365 *pupper = *plower + span - incr;
366 } else {
367 *plower = *pupper + (incr > 0 ? 1 : -1);
368 }
369 } else {
370 *pstride = span * nth;
371 *plower = *plower + (span * tid);
372 *pupper = *plower + span - incr;
373 }
374 if (plastiter != NULL)
375 *plastiter = (tid == (nchunks - 1) % nth);
376 break;
377 }
378 case kmp_sch_static_balanced_chunked: {
379 T old_upper = *pupper;
380 KMP_DEBUG_ASSERT(nth != 0);
381 // round up to make sure the chunk is enough to cover all iterations
382 UT span = (trip_count + nth - 1) / nth;
383
384 // perform chunk adjustment
385 chunk = (span + chunk - 1) & ~(chunk - 1);
386
387 span = chunk * incr;
388 *plower = *plower + (span * tid);
389 *pupper = *plower + span - incr;
390 if (incr > 0) {
391 if (*pupper > old_upper)
392 *pupper = old_upper;
393 } else if (*pupper < old_upper)
394 *pupper = old_upper;
395
396 if (plastiter != NULL) {
397 KMP_DEBUG_ASSERT(chunk != 0);
398 *plastiter = (tid == ((trip_count - 1) / (UT)chunk));
399 }
400 break;
401 }
402 default:
403 KMP_ASSERT2(0, "__kmpc_for_static_init: unknown scheduling type");
404 break;
405 }
406
407#if USE_ITT_BUILD
408 // Report loop metadata
409 if (KMP_MASTER_TID(tid) && __itt_metadata_add_ptr &&
410 __kmp_forkjoin_frames_mode == 3 && th->th.th_teams_microtask == NULL &&
411 team->t.t_active_level == 1) {
412 kmp_uint64 cur_chunk = chunk;
413 check_loc(loc);
414 // Calculate chunk in case it was not specified; it is specified for
415 // kmp_sch_static_chunked
416 if (schedtype == kmp_sch_static) {
417 KMP_DEBUG_ASSERT(nth != 0);
418 cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0);
419 }
420 // 0 - "static" schedule
421 __kmp_itt_metadata_loop(loc, 0, trip_count, cur_chunk);
422 }
423#endif
424#ifdef KMP_DEBUG
425 {
426 char *buff;
427 // create format specifiers before the debug output
428 buff = __kmp_str_format("__kmpc_for_static_init: liter=%%d lower=%%%s "
429 "upper=%%%s stride = %%%s signed?<%s>\n",
430 traits_t<T>::spec, traits_t<T>::spec,
431 traits_t<ST>::spec, traits_t<T>::spec);
432 KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
433 __kmp_str_free(&buff);
434 }
435#endif
436 KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
437
438 OMPT_LOOP_BEGIN(trip_count);
439#if OMPT_SUPPORT && OMPT_OPTIONAL
440 if (ompt_enabled.ompt_callback_dispatch) {
441 ompt_dispatch_t dispatch_type;
442 ompt_data_t instance = ompt_data_none;
443 ompt_dispatch_chunk_t dispatch_chunk;
444 if (ompt_work_type == ompt_work_sections) {
445 dispatch_type = ompt_dispatch_section;
446 instance.ptr = codeptr;
447 } else {
448 OMPT_GET_DISPATCH_CHUNK(dispatch_chunk, *plower, *pupper, incr);
449 dispatch_type = (ompt_work_type == ompt_work_distribute)
450 ? ompt_dispatch_distribute_chunk
451 : ompt_dispatch_ws_loop_chunk;
452 instance.ptr = &dispatch_chunk;
453 }
454 ompt_callbacks.ompt_callback(ompt_callback_dispatch)(
455 &(team_info->parallel_data), &(task_info->task_data), dispatch_type,
456 instance);
457 }
458#endif
459
460 KMP_STATS_LOOP_END(OMP_loop_static_iterations);
461 return;
462}
463
464template <typename T>
465static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid,
466 kmp_int32 schedule, kmp_int32 *plastiter,
467 T *plower, T *pupper, T *pupperDist,
468 typename traits_t<T>::signed_t *pstride,
469 typename traits_t<T>::signed_t incr,
470 typename traits_t<T>::signed_t chunk
471#if OMPT_SUPPORT && OMPT_OPTIONAL
472 ,
473 void *codeptr
474#endif
475) {
476 KMP_COUNT_BLOCK(OMP_DISTRIBUTE);
477 KMP_PUSH_PARTITIONED_TIMER(OMP_distribute);
478 KMP_PUSH_PARTITIONED_TIMER(OMP_distribute_scheduling);
479 typedef typename traits_t<T>::unsigned_t UT;
480 typedef typename traits_t<T>::signed_t ST;
481 kmp_uint32 tid;
482 kmp_uint32 nth;
483 kmp_uint32 team_id;
484 kmp_uint32 nteams;
485 UT trip_count;
486 kmp_team_t *team;
487 kmp_info_t *th;
488
489 KMP_DEBUG_ASSERT(plastiter && plower && pupper && pupperDist && pstride);
490 KE_TRACE(10, ("__kmpc_dist_for_static_init called (%d)\n", gtid));
491 __kmp_assert_valid_gtid(gtid);
492#ifdef KMP_DEBUG
493 {
494 char *buff;
495 // create format specifiers before the debug output
496 buff = __kmp_str_format(
497 "__kmpc_dist_for_static_init: T#%%d schedLoop=%%d liter=%%d "
498 "iter=(%%%s, %%%s, %%%s) chunk=%%%s signed?<%s>\n",
499 traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
500 traits_t<ST>::spec, traits_t<T>::spec);
501 KD_TRACE(100,
502 (buff, gtid, schedule, *plastiter, *plower, *pupper, incr, chunk));
503 __kmp_str_free(&buff);
504 }
505#endif
506
507 if (__kmp_env_consistency_check) {
508 __kmp_push_workshare(gtid, ct_pdo, loc);
509 if (incr == 0) {
510 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
511 loc);
512 }
513 if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
514 // The loop is illegal.
515 // Some zero-trip loops maintained by compiler, e.g.:
516 // for(i=10;i<0;++i) // lower >= upper - run-time check
517 // for(i=0;i>10;--i) // lower <= upper - run-time check
518 // for(i=0;i>10;++i) // incr > 0 - compile-time check
519 // for(i=10;i<0;--i) // incr < 0 - compile-time check
520 // Compiler does not check the following illegal loops:
521 // for(i=0;i<10;i+=incr) // where incr<0
522 // for(i=10;i>0;i-=incr) // where incr<0
523 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
524 }
525 }
526 tid = __kmp_tid_from_gtid(gtid);
527 th = __kmp_threads[gtid];
528 nth = th->th.th_team_nproc;
529 team = th->th.th_team;
530 KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
531 // skip optional serialized teams to prevent this from using the wrong teams
532 // information when called after __kmp_serialized_parallel
533 // TODO: make __kmp_serialized_parallel eventually call __kmp_fork_in_teams
534 // to address this edge case
535 while (team->t.t_parent && team->t.t_serialized)
536 team = team->t.t_parent;
537 nteams = th->th.th_teams_size.nteams;
538 team_id = team->t.t_master_tid;
539 KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
540
541 // compute global trip count
542 if (incr == 1) {
543 trip_count = *pupper - *plower + 1;
544 } else if (incr == -1) {
545 trip_count = *plower - *pupper + 1;
546 } else if (incr > 0) {
547 // upper-lower can exceed the limit of signed type
548 trip_count = (UT)(*pupper - *plower) / incr + 1;
549 } else {
550 KMP_DEBUG_ASSERT(incr != 0);
551 trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
552 }
553
554 *pstride = *pupper - *plower; // just in case (can be unused)
555 if (trip_count <= nteams) {
556 KMP_DEBUG_ASSERT(
557 __kmp_static == kmp_sch_static_greedy ||
558 __kmp_static ==
559 kmp_sch_static_balanced); // Unknown static scheduling type.
560 // only primary threads of some teams get single iteration, other threads
561 // get nothing
562 if (team_id < trip_count && tid == 0) {
563 *pupper = *pupperDist = *plower = *plower + team_id * incr;
564 } else {
565 *pupperDist = *pupper;
566 *plower = *pupper + incr; // compiler should skip loop body
567 }
568 if (plastiter != NULL)
569 *plastiter = (tid == 0 && team_id == trip_count - 1);
570 } else {
571 // Get the team's chunk first (each team gets at most one chunk)
572 KMP_DEBUG_ASSERT(nteams != 0);
573 if (__kmp_static == kmp_sch_static_balanced) {
574 UT chunkD = trip_count / nteams;
575 UT extras = trip_count % nteams;
576 *plower +=
577 incr * (team_id * chunkD + (team_id < extras ? team_id : extras));
578 *pupperDist = *plower + chunkD * incr - (team_id < extras ? 0 : incr);
579 if (plastiter != NULL)
580 *plastiter = (team_id == nteams - 1);
581 } else {
582 T chunk_inc_count =
583 (trip_count / nteams + ((trip_count % nteams) ? 1 : 0)) * incr;
584 T upper = *pupper;
585 KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
586 // Unknown static scheduling type.
587 *plower += team_id * chunk_inc_count;
588 *pupperDist = *plower + chunk_inc_count - incr;
589 // Check/correct bounds if needed
590 if (incr > 0) {
591 if (*pupperDist < *plower)
592 *pupperDist = traits_t<T>::max_value;
593 if (plastiter != NULL)
594 *plastiter = *plower <= upper && *pupperDist > upper - incr;
595 if (*pupperDist > upper)
596 *pupperDist = upper; // tracker C73258
597 if (*plower > *pupperDist) {
598 *pupper = *pupperDist; // no iterations available for the team
599 goto end;
600 }
601 } else {
602 if (*pupperDist > *plower)
603 *pupperDist = traits_t<T>::min_value;
604 if (plastiter != NULL)
605 *plastiter = *plower >= upper && *pupperDist < upper - incr;
606 if (*pupperDist < upper)
607 *pupperDist = upper; // tracker C73258
608 if (*plower < *pupperDist) {
609 *pupper = *pupperDist; // no iterations available for the team
610 goto end;
611 }
612 }
613 }
614 // Get the parallel loop chunk now (for thread)
615 // compute trip count for team's chunk
616 if (incr == 1) {
617 trip_count = *pupperDist - *plower + 1;
618 } else if (incr == -1) {
619 trip_count = *plower - *pupperDist + 1;
620 } else if (incr > 1) {
621 // upper-lower can exceed the limit of signed type
622 trip_count = (UT)(*pupperDist - *plower) / incr + 1;
623 } else {
624 KMP_DEBUG_ASSERT(incr != 0);
625 trip_count = (UT)(*plower - *pupperDist) / (-incr) + 1;
626 }
627 KMP_DEBUG_ASSERT(trip_count);
628 switch (schedule) {
629 case kmp_sch_static: {
630 if (trip_count <= nth) {
631 KMP_DEBUG_ASSERT(
632 __kmp_static == kmp_sch_static_greedy ||
633 __kmp_static ==
634 kmp_sch_static_balanced); // Unknown static scheduling type.
635 if (tid < trip_count)
636 *pupper = *plower = *plower + tid * incr;
637 else
638 *plower = *pupper + incr; // no iterations available
639 if (plastiter != NULL)
640 if (*plastiter != 0 && !(tid == trip_count - 1))
641 *plastiter = 0;
642 } else {
643 KMP_DEBUG_ASSERT(nth != 0);
644 if (__kmp_static == kmp_sch_static_balanced) {
645 UT chunkL = trip_count / nth;
646 UT extras = trip_count % nth;
647 *plower += incr * (tid * chunkL + (tid < extras ? tid : extras));
648 *pupper = *plower + chunkL * incr - (tid < extras ? 0 : incr);
649 if (plastiter != NULL)
650 if (*plastiter != 0 && !(tid == nth - 1))
651 *plastiter = 0;
652 } else {
653 T chunk_inc_count =
654 (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
655 T upper = *pupperDist;
656 KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
657 // Unknown static scheduling type.
658 *plower += tid * chunk_inc_count;
659 *pupper = *plower + chunk_inc_count - incr;
660 if (incr > 0) {
661 if (*pupper < *plower)
662 *pupper = traits_t<T>::max_value;
663 if (plastiter != NULL)
664 if (*plastiter != 0 &&
665 !(*plower <= upper && *pupper > upper - incr))
666 *plastiter = 0;
667 if (*pupper > upper)
668 *pupper = upper; // tracker C73258
669 } else {
670 if (*pupper > *plower)
671 *pupper = traits_t<T>::min_value;
672 if (plastiter != NULL)
673 if (*plastiter != 0 &&
674 !(*plower >= upper && *pupper < upper - incr))
675 *plastiter = 0;
676 if (*pupper < upper)
677 *pupper = upper; // tracker C73258
678 }
679 }
680 }
681 break;
682 }
683 case kmp_sch_static_chunked: {
684 ST span;
685 if (chunk < 1)
686 chunk = 1;
687 span = chunk * incr;
688 *pstride = span * nth;
689 *plower = *plower + (span * tid);
690 *pupper = *plower + span - incr;
691 if (plastiter != NULL) {
692 KMP_DEBUG_ASSERT(chunk != 0);
693 if (*plastiter != 0 && !(tid == ((trip_count - 1) / (UT)chunk) % nth))
694 *plastiter = 0;
695 }
696 break;
697 }
698 default:
699 KMP_ASSERT2(0,
700 "__kmpc_dist_for_static_init: unknown loop scheduling type");
701 break;
702 }
703 }
704end:;
705#ifdef KMP_DEBUG
706 {
707 char *buff;
708 // create format specifiers before the debug output
709 buff = __kmp_str_format(
710 "__kmpc_dist_for_static_init: last=%%d lo=%%%s up=%%%s upDist=%%%s "
711 "stride=%%%s signed?<%s>\n",
712 traits_t<T>::spec, traits_t<T>::spec, traits_t<T>::spec,
713 traits_t<ST>::spec, traits_t<T>::spec);
714 KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pupperDist, *pstride));
715 __kmp_str_free(&buff);
716 }
717#endif
718 KE_TRACE(10, ("__kmpc_dist_for_static_init: T#%d return\n", gtid));
719#if OMPT_SUPPORT && OMPT_OPTIONAL
720 if (ompt_enabled.ompt_callback_work || ompt_enabled.ompt_callback_dispatch) {
721 ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL);
722 ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
723 if (ompt_enabled.ompt_callback_work) {
724 ompt_callbacks.ompt_callback(ompt_callback_work)(
725 ompt_work_distribute, ompt_scope_begin, &(team_info->parallel_data),
726 &(task_info->task_data), 0, codeptr);
727 }
728 if (ompt_enabled.ompt_callback_dispatch) {
729 ompt_data_t instance = ompt_data_none;
730 ompt_dispatch_chunk_t dispatch_chunk;
731 OMPT_GET_DISPATCH_CHUNK(dispatch_chunk, *plower, *pupperDist, incr);
732 instance.ptr = &dispatch_chunk;
733 ompt_callbacks.ompt_callback(ompt_callback_dispatch)(
734 &(team_info->parallel_data), &(task_info->task_data),
735 ompt_dispatch_distribute_chunk, instance);
736 }
737 }
738#endif // OMPT_SUPPORT && OMPT_OPTIONAL
739 KMP_STATS_LOOP_END(OMP_distribute_iterations);
740 return;
741}
742
743template <typename T>
744static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid,
745 kmp_int32 *p_last, T *p_lb, T *p_ub,
746 typename traits_t<T>::signed_t *p_st,
747 typename traits_t<T>::signed_t incr,
748 typename traits_t<T>::signed_t chunk) {
749 // The routine returns the first chunk distributed to the team and
750 // stride for next chunks calculation.
751 // Last iteration flag set for the team that will execute
752 // the last iteration of the loop.
753 // The routine is called for dist_schedule(static,chunk) only.
754 typedef typename traits_t<T>::unsigned_t UT;
755 typedef typename traits_t<T>::signed_t ST;
756 kmp_uint32 team_id;
757 kmp_uint32 nteams;
758 UT trip_count;
759 T lower;
760 T upper;
761 ST span;
762 kmp_team_t *team;
763 kmp_info_t *th;
764
765 KMP_DEBUG_ASSERT(p_last && p_lb && p_ub && p_st);
766 KE_TRACE(10, ("__kmp_team_static_init called (%d)\n", gtid));
767 __kmp_assert_valid_gtid(gtid);
768#ifdef KMP_DEBUG
769 {
770 char *buff;
771 // create format specifiers before the debug output
772 buff = __kmp_str_format("__kmp_team_static_init enter: T#%%d liter=%%d "
773 "iter=(%%%s, %%%s, %%%s) chunk %%%s; signed?<%s>\n",
774 traits_t<T>::spec, traits_t<T>::spec,
775 traits_t<ST>::spec, traits_t<ST>::spec,
776 traits_t<T>::spec);
777 KD_TRACE(100, (buff, gtid, *p_last, *p_lb, *p_ub, *p_st, chunk));
778 __kmp_str_free(&buff);
779 }
780#endif
781
782 lower = *p_lb;
783 upper = *p_ub;
784 if (__kmp_env_consistency_check) {
785 if (incr == 0) {
786 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
787 loc);
788 }
789 if (incr > 0 ? (upper < lower) : (lower < upper)) {
790 // The loop is illegal.
791 // Some zero-trip loops maintained by compiler, e.g.:
792 // for(i=10;i<0;++i) // lower >= upper - run-time check
793 // for(i=0;i>10;--i) // lower <= upper - run-time check
794 // for(i=0;i>10;++i) // incr > 0 - compile-time check
795 // for(i=10;i<0;--i) // incr < 0 - compile-time check
796 // Compiler does not check the following illegal loops:
797 // for(i=0;i<10;i+=incr) // where incr<0
798 // for(i=10;i>0;i-=incr) // where incr<0
799 __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
800 }
801 }
802 th = __kmp_threads[gtid];
803 team = th->th.th_team;
804 KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
805 nteams = th->th.th_teams_size.nteams;
806 team_id = team->t.t_master_tid;
807 KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
808
809 // compute trip count
810 if (incr == 1) {
811 trip_count = upper - lower + 1;
812 } else if (incr == -1) {
813 trip_count = lower - upper + 1;
814 } else if (incr > 0) {
815 // upper-lower can exceed the limit of signed type
816 trip_count = (UT)(upper - lower) / incr + 1;
817 } else {
818 KMP_DEBUG_ASSERT(incr != 0);
819 trip_count = (UT)(lower - upper) / (-incr) + 1;
820 }
821 if (chunk < 1)
822 chunk = 1;
823 span = chunk * incr;
824 *p_st = span * nteams;
825 *p_lb = lower + (span * team_id);
826 *p_ub = *p_lb + span - incr;
827 if (p_last != NULL) {
828 KMP_DEBUG_ASSERT(chunk != 0);
829 *p_last = (team_id == ((trip_count - 1) / (UT)chunk) % nteams);
830 }
831 // Correct upper bound if needed
832 if (incr > 0) {
833 if (*p_ub < *p_lb) // overflow?
834 *p_ub = traits_t<T>::max_value;
835 if (*p_ub > upper)
836 *p_ub = upper; // tracker C73258
837 } else { // incr < 0
838 if (*p_ub > *p_lb)
839 *p_ub = traits_t<T>::min_value;
840 if (*p_ub < upper)
841 *p_ub = upper; // tracker C73258
842 }
843#ifdef KMP_DEBUG
844 {
845 char *buff;
846 // create format specifiers before the debug output
847 buff =
848 __kmp_str_format("__kmp_team_static_init exit: T#%%d team%%u liter=%%d "
849 "iter=(%%%s, %%%s, %%%s) chunk %%%s\n",
850 traits_t<T>::spec, traits_t<T>::spec,
851 traits_t<ST>::spec, traits_t<ST>::spec);
852 KD_TRACE(100, (buff, gtid, team_id, *p_last, *p_lb, *p_ub, *p_st, chunk));
853 __kmp_str_free(&buff);
854 }
855#endif
856}
857
858//------------------------------------------------------------------------------
859extern "C" {
881void __kmpc_for_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
882 kmp_int32 *plastiter, kmp_int32 *plower,
883 kmp_int32 *pupper, kmp_int32 *pstride,
884 kmp_int32 incr, kmp_int32 chunk) {
885 __kmp_for_static_init<kmp_int32>(loc, gtid, schedtype, plastiter, plower,
886 pupper, pstride, incr, chunk
887#if OMPT_SUPPORT && OMPT_OPTIONAL
888 ,
889 OMPT_GET_RETURN_ADDRESS(0)
890#endif
891 );
892}
893
897void __kmpc_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
898 kmp_int32 schedtype, kmp_int32 *plastiter,
899 kmp_uint32 *plower, kmp_uint32 *pupper,
900 kmp_int32 *pstride, kmp_int32 incr,
901 kmp_int32 chunk) {
902 __kmp_for_static_init<kmp_uint32>(loc, gtid, schedtype, plastiter, plower,
903 pupper, pstride, incr, chunk
904#if OMPT_SUPPORT && OMPT_OPTIONAL
905 ,
906 OMPT_GET_RETURN_ADDRESS(0)
907#endif
908 );
909}
910
914void __kmpc_for_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
915 kmp_int32 *plastiter, kmp_int64 *plower,
916 kmp_int64 *pupper, kmp_int64 *pstride,
917 kmp_int64 incr, kmp_int64 chunk) {
918 __kmp_for_static_init<kmp_int64>(loc, gtid, schedtype, plastiter, plower,
919 pupper, pstride, incr, chunk
920#if OMPT_SUPPORT && OMPT_OPTIONAL
921 ,
922 OMPT_GET_RETURN_ADDRESS(0)
923#endif
924 );
925}
926
930void __kmpc_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
931 kmp_int32 schedtype, kmp_int32 *plastiter,
932 kmp_uint64 *plower, kmp_uint64 *pupper,
933 kmp_int64 *pstride, kmp_int64 incr,
934 kmp_int64 chunk) {
935 __kmp_for_static_init<kmp_uint64>(loc, gtid, schedtype, plastiter, plower,
936 pupper, pstride, incr, chunk
937#if OMPT_SUPPORT && OMPT_OPTIONAL
938 ,
939 OMPT_GET_RETURN_ADDRESS(0)
940#endif
941 );
942}
947#if OMPT_SUPPORT && OMPT_OPTIONAL
948#define OMPT_CODEPTR_ARG , OMPT_GET_RETURN_ADDRESS(0)
949#else
950#define OMPT_CODEPTR_ARG
951#endif
952
975void __kmpc_dist_for_static_init_4(ident_t *loc, kmp_int32 gtid,
976 kmp_int32 schedule, kmp_int32 *plastiter,
977 kmp_int32 *plower, kmp_int32 *pupper,
978 kmp_int32 *pupperD, kmp_int32 *pstride,
979 kmp_int32 incr, kmp_int32 chunk) {
980 __kmp_dist_for_static_init<kmp_int32>(loc, gtid, schedule, plastiter, plower,
981 pupper, pupperD, pstride, incr,
982 chunk OMPT_CODEPTR_ARG);
983}
984
988void __kmpc_dist_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
989 kmp_int32 schedule, kmp_int32 *plastiter,
990 kmp_uint32 *plower, kmp_uint32 *pupper,
991 kmp_uint32 *pupperD, kmp_int32 *pstride,
992 kmp_int32 incr, kmp_int32 chunk) {
993 __kmp_dist_for_static_init<kmp_uint32>(loc, gtid, schedule, plastiter, plower,
994 pupper, pupperD, pstride, incr,
995 chunk OMPT_CODEPTR_ARG);
996}
997
1001void __kmpc_dist_for_static_init_8(ident_t *loc, kmp_int32 gtid,
1002 kmp_int32 schedule, kmp_int32 *plastiter,
1003 kmp_int64 *plower, kmp_int64 *pupper,
1004 kmp_int64 *pupperD, kmp_int64 *pstride,
1005 kmp_int64 incr, kmp_int64 chunk) {
1006 __kmp_dist_for_static_init<kmp_int64>(loc, gtid, schedule, plastiter, plower,
1007 pupper, pupperD, pstride, incr,
1008 chunk OMPT_CODEPTR_ARG);
1009}
1010
1014void __kmpc_dist_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
1015 kmp_int32 schedule, kmp_int32 *plastiter,
1016 kmp_uint64 *plower, kmp_uint64 *pupper,
1017 kmp_uint64 *pupperD, kmp_int64 *pstride,
1018 kmp_int64 incr, kmp_int64 chunk) {
1019 __kmp_dist_for_static_init<kmp_uint64>(loc, gtid, schedule, plastiter, plower,
1020 pupper, pupperD, pstride, incr,
1021 chunk OMPT_CODEPTR_ARG);
1022}
1027//------------------------------------------------------------------------------
1028// Auxiliary routines for Distribute Parallel Loop construct implementation
1029// Transfer call to template< type T >
1030// __kmp_team_static_init( ident_t *loc, int gtid,
1031// int *p_last, T *lb, T *ub, ST *st, ST incr, ST chunk )
1032
1053void __kmpc_team_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
1054 kmp_int32 *p_lb, kmp_int32 *p_ub,
1055 kmp_int32 *p_st, kmp_int32 incr,
1056 kmp_int32 chunk) {
1057 KMP_DEBUG_ASSERT(__kmp_init_serial);
1058 __kmp_team_static_init<kmp_int32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
1059 chunk);
1060}
1061
1065void __kmpc_team_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
1066 kmp_uint32 *p_lb, kmp_uint32 *p_ub,
1067 kmp_int32 *p_st, kmp_int32 incr,
1068 kmp_int32 chunk) {
1069 KMP_DEBUG_ASSERT(__kmp_init_serial);
1070 __kmp_team_static_init<kmp_uint32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
1071 chunk);
1072}
1073
1077void __kmpc_team_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
1078 kmp_int64 *p_lb, kmp_int64 *p_ub,
1079 kmp_int64 *p_st, kmp_int64 incr,
1080 kmp_int64 chunk) {
1081 KMP_DEBUG_ASSERT(__kmp_init_serial);
1082 __kmp_team_static_init<kmp_int64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
1083 chunk);
1084}
1085
1089void __kmpc_team_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
1090 kmp_uint64 *p_lb, kmp_uint64 *p_ub,
1091 kmp_int64 *p_st, kmp_int64 incr,
1092 kmp_int64 chunk) {
1093 KMP_DEBUG_ASSERT(__kmp_init_serial);
1094 __kmp_team_static_init<kmp_uint64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
1095 chunk);
1096}
1101} // extern "C"
@ KMP_IDENT_KMPC
Definition kmp.h:179
@ KMP_IDENT_WORK_LOOP
Definition kmp.h:197
@ KMP_IDENT_WORK_SECTIONS
Definition kmp.h:199
@ KMP_IDENT_WORK_DISTRIBUTE
Definition kmp.h:201
#define KMP_COUNT_VALUE(name, value)
Adds value to specified timer (name).
Definition kmp_stats.h:898
#define KMP_COUNT_BLOCK(name)
Increments specified counter (name).
Definition kmp_stats.h:911
void __kmpc_for_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter, kmp_int64 *plower, kmp_int64 *pupper, kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk)
void __kmpc_dist_for_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 schedule, kmp_int32 *plastiter, kmp_int64 *plower, kmp_int64 *pupper, kmp_int64 *pupperD, kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk)
void __kmpc_for_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter, kmp_uint32 *plower, kmp_uint32 *pupper, kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_team_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last, kmp_int64 *p_lb, kmp_int64 *p_ub, kmp_int64 *p_st, kmp_int64 incr, kmp_int64 chunk)
void __kmpc_dist_for_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 schedule, kmp_int32 *plastiter, kmp_uint32 *plower, kmp_uint32 *pupper, kmp_uint32 *pupperD, kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_team_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last, kmp_uint64 *p_lb, kmp_uint64 *p_ub, kmp_int64 *p_st, kmp_int64 incr, kmp_int64 chunk)
void __kmpc_for_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter, kmp_uint64 *plower, kmp_uint64 *pupper, kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk)
void __kmpc_team_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last, kmp_uint32 *p_lb, kmp_uint32 *p_ub, kmp_int32 *p_st, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_dist_for_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 schedule, kmp_int32 *plastiter, kmp_int32 *plower, kmp_int32 *pupper, kmp_int32 *pupperD, kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_for_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype, kmp_int32 *plastiter, kmp_int32 *plower, kmp_int32 *pupper, kmp_int32 *pstride, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_team_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last, kmp_int32 *p_lb, kmp_int32 *p_ub, kmp_int32 *p_st, kmp_int32 incr, kmp_int32 chunk)
void __kmpc_dist_for_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 schedule, kmp_int32 *plastiter, kmp_uint64 *plower, kmp_uint64 *pupper, kmp_uint64 *pupperD, kmp_int64 *pstride, kmp_int64 incr, kmp_int64 chunk)
@ kmp_sch_static
Definition kmp.h:343
@ kmp_distribute_static
Definition kmp.h:379
@ kmp_ord_upper
Definition kmp.h:375
Definition kmp.h:217
char const * psource
Definition kmp.h:227
kmp_int32 flags
Definition kmp.h:219