13#include "kmp_wait_release.h"
14#include "kmp_barrier.h"
18#include "ompt-specific.h"
20#include "kmp_affinity.h"
24#define USE_NGO_STORES 1
27#if KMP_MIC && USE_NGO_STORES
29#define ngo_load(src) __m512d Vt = _mm512_load_pd((void *)(src))
30#define ngo_store_icvs(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt)
31#define ngo_store_go(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt)
32#define ngo_sync() __asm__ volatile("lock; addl $0,0(%%rsp)" ::: "memory")
34#define ngo_load(src) ((void)0)
35#define ngo_store_icvs(dst, src) copy_icvs((dst), (src))
36#define ngo_store_go(dst, src) KMP_MEMCPY((dst), (src), CACHE_LINE)
37#define ngo_sync() ((void)0)
40void __kmp_print_structure(
void);
47void distributedBarrier::computeVarsForN(
size_t n) {
50 int socket_level = __kmp_topology->get_level(KMP_HW_SOCKET);
51 int core_level = __kmp_topology->get_level(KMP_HW_CORE);
52 int ncores_per_socket =
53 __kmp_topology->calculate_ratio(core_level, socket_level);
54 nsockets = __kmp_topology->get_count(socket_level);
58 if (ncores_per_socket <= 0)
59 ncores_per_socket = 1;
61 threads_per_go = ncores_per_socket >> 1;
62 if (!fix_threads_per_go) {
64 if (threads_per_go > 4) {
65 if (KMP_OPTIMIZE_FOR_REDUCTIONS) {
66 threads_per_go = threads_per_go >> 1;
68 if (threads_per_go > 4 && nsockets == 1)
69 threads_per_go = threads_per_go >> 1;
72 if (threads_per_go == 0)
74 fix_threads_per_go =
true;
75 num_gos = n / threads_per_go;
76 if (n % threads_per_go)
78 if (nsockets == 1 || num_gos == 1)
81 num_groups = num_gos / nsockets;
82 if (num_gos % nsockets)
87 gos_per_group = num_gos / num_groups;
88 if (num_gos % num_groups)
90 threads_per_group = threads_per_go * gos_per_group;
92 num_gos = n / threads_per_go;
93 if (n % threads_per_go)
98 num_groups = num_gos / 2;
102 gos_per_group = num_gos / num_groups;
103 if (num_gos % num_groups)
105 threads_per_group = threads_per_go * gos_per_group;
109void distributedBarrier::computeGo(
size_t n) {
111 for (num_gos = 1;; num_gos++)
112 if (IDEAL_CONTENTION * num_gos >= n)
114 threads_per_go = n / num_gos;
117 while (num_gos > MAX_GOS) {
119 num_gos = n / threads_per_go;
120 if (n % threads_per_go)
128void distributedBarrier::resize(
size_t nthr) {
129 KMP_DEBUG_ASSERT(nthr > max_threads);
132 max_threads = nthr * 2;
135 for (
int i = 0; i < MAX_ITERS; ++i) {
137 flags[i] = (flags_s *)KMP_INTERNAL_REALLOC(flags[i],
138 max_threads *
sizeof(flags_s));
140 flags[i] = (flags_s *)KMP_INTERNAL_MALLOC(max_threads *
sizeof(flags_s));
144 go = (go_s *)KMP_INTERNAL_REALLOC(go, max_threads *
sizeof(go_s));
146 go = (go_s *)KMP_INTERNAL_MALLOC(max_threads *
sizeof(go_s));
149 iter = (iter_s *)KMP_INTERNAL_REALLOC(iter, max_threads *
sizeof(iter_s));
151 iter = (iter_s *)KMP_INTERNAL_MALLOC(max_threads *
sizeof(iter_s));
155 (sleep_s *)KMP_INTERNAL_REALLOC(sleep, max_threads *
sizeof(sleep_s));
157 sleep = (sleep_s *)KMP_INTERNAL_MALLOC(max_threads *
sizeof(sleep_s));
163kmp_uint64 distributedBarrier::go_release() {
164 kmp_uint64 next_go = iter[0].iter + distributedBarrier::MAX_ITERS;
165 for (
size_t j = 0; j < num_gos; j++) {
166 go[j].go.store(next_go);
171void distributedBarrier::go_reset() {
172 for (
size_t j = 0; j < max_threads; ++j) {
173 for (
size_t i = 0; i < distributedBarrier::MAX_ITERS; ++i) {
174 flags[i][j].stillNeed = 1;
183void distributedBarrier::init(
size_t nthr) {
184 size_t old_max = max_threads;
185 if (nthr > max_threads) {
189 for (
size_t i = 0; i < max_threads; i++) {
190 for (
size_t j = 0; j < distributedBarrier::MAX_ITERS; j++) {
191 flags[j][i].stillNeed = 1;
196 sleep[i].sleep =
false;
200 computeVarsForN(nthr);
204 if (team_icvs == NULL)
205 team_icvs = __kmp_allocate(
sizeof(kmp_internal_control_t));
210void __kmp_dist_barrier_wakeup(
enum barrier_type bt, kmp_team_t *team,
211 size_t start,
size_t stop,
size_t inc,
213 KMP_DEBUG_ASSERT(__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME);
214 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))
217 kmp_info_t **other_threads = team->t.t_threads;
218 for (
size_t thr = start; thr < stop; thr += inc) {
219 KMP_DEBUG_ASSERT(other_threads[thr]);
220 int gtid = other_threads[thr]->th.th_info.ds.ds_gtid;
222 __kmp_atomic_resume_64(gtid, (kmp_atomic_flag_64<> *)NULL);
226static void __kmp_dist_barrier_gather(
227 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
228 void (*reduce)(
void *,
void *) USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
229 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_dist_gather);
231 distributedBarrier *b;
232 kmp_info_t **other_threads;
233 kmp_uint64 my_current_iter, my_next_iter;
237 team = this_thr->th.th_team;
238 nproc = this_thr->th.th_team_nproc;
239 other_threads = team->t.t_threads;
241 my_current_iter = b->iter[tid].iter;
242 my_next_iter = (my_current_iter + 1) % distributedBarrier::MAX_ITERS;
243 group_leader = ((tid % b->threads_per_group) == 0);
246 (
"__kmp_dist_barrier_gather: T#%d(%d:%d) enter; barrier type %d\n",
247 gtid, team->t.t_id, tid, bt));
249#if USE_ITT_BUILD && USE_ITT_NOTIFY
251 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) {
252 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time =
253 __itt_get_timestamp();
259 size_t group_start = tid + 1;
260 size_t group_end = tid + b->threads_per_group;
261 size_t threads_pending = 0;
263 if (group_end > nproc)
268 for (
size_t thr = group_start; thr < group_end; thr++) {
270 threads_pending += b->flags[my_current_iter][thr].stillNeed;
273 if (__kmp_tasking_mode != tskm_immediate_exec) {
274 kmp_task_team_t *task_team = this_thr->th.th_task_team;
275 if (task_team != NULL) {
276 if (TCR_SYNC_4(task_team->tt.tt_active)) {
277 if (KMP_TASKING_ENABLED(task_team)) {
278 int tasks_completed = FALSE;
279 __kmp_atomic_execute_tasks_64(
280 this_thr, gtid, (kmp_atomic_flag_64<> *)NULL, FALSE,
281 &tasks_completed USE_ITT_BUILD_ARG(itt_sync_obj), 0);
283 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
286 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
289 if (TCR_4(__kmp_global.g.g_done)) {
290 if (__kmp_global.g.g_abort)
291 __kmp_abort_thread();
293 }
else if (__kmp_tasking_mode != tskm_immediate_exec &&
294 this_thr->th.th_reap_state == KMP_SAFE_TO_REAP) {
295 this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP;
297 }
while (threads_pending > 0);
300 OMPT_REDUCTION_DECL(this_thr, gtid);
301 OMPT_REDUCTION_BEGIN;
303 for (
size_t thr = group_start; thr < group_end; thr++) {
304 (*reduce)(this_thr->th.th_local.reduce_data,
305 other_threads[thr]->th.th_local.reduce_data);
311 b->flags[my_next_iter][tid].stillNeed = 1;
314 b->flags[my_current_iter][tid].stillNeed = 0;
318 for (
size_t thr = 0; thr < nproc; thr += b->threads_per_group) {
319 threads_pending += b->flags[my_current_iter][thr].stillNeed;
322 if (__kmp_tasking_mode != tskm_immediate_exec) {
323 kmp_task_team_t *task_team = this_thr->th.th_task_team;
324 if (task_team != NULL) {
325 if (TCR_SYNC_4(task_team->tt.tt_active)) {
326 if (KMP_TASKING_ENABLED(task_team)) {
327 int tasks_completed = FALSE;
328 __kmp_atomic_execute_tasks_64(
329 this_thr, gtid, (kmp_atomic_flag_64<> *)NULL, FALSE,
330 &tasks_completed USE_ITT_BUILD_ARG(itt_sync_obj), 0);
332 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
335 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
338 if (TCR_4(__kmp_global.g.g_done)) {
339 if (__kmp_global.g.g_abort)
340 __kmp_abort_thread();
342 }
else if (__kmp_tasking_mode != tskm_immediate_exec &&
343 this_thr->th.th_reap_state == KMP_SAFE_TO_REAP) {
344 this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP;
346 }
while (threads_pending > 0);
349 if (KMP_MASTER_TID(tid)) {
350 OMPT_REDUCTION_DECL(this_thr, gtid);
351 OMPT_REDUCTION_BEGIN;
352 for (
size_t thr = b->threads_per_group; thr < nproc;
353 thr += b->threads_per_group) {
354 (*reduce)(this_thr->th.th_local.reduce_data,
355 other_threads[thr]->th.th_local.reduce_data);
362 b->flags[my_next_iter][tid].stillNeed = 1;
365 b->flags[my_current_iter][tid].stillNeed = 0;
371 (
"__kmp_dist_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n",
372 gtid, team->t.t_id, tid, bt));
375static void __kmp_dist_barrier_release(
376 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
377 int propagate_icvs USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
378 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_dist_release);
380 distributedBarrier *b;
381 kmp_bstate_t *thr_bar;
382 kmp_uint64 my_current_iter, next_go;
386 KA_TRACE(20, (
"__kmp_dist_barrier_release: T#%d(%d) enter; barrier type %d\n",
389 thr_bar = &this_thr->th.th_bar[bt].bb;
391 if (!KMP_MASTER_TID(tid)) {
394 if (this_thr->th.th_used_in_team.load() != 1 &&
395 this_thr->th.th_used_in_team.load() != 3) {
400 kmp_flag_32<false, false> my_flag(&(this_thr->th.th_used_in_team), 3);
401 if (KMP_COMPARE_AND_STORE_ACQ32(&(this_thr->th.th_used_in_team), 2,
403 this_thr->th.th_used_in_team.load() == 0) {
404 my_flag.wait(this_thr,
true USE_ITT_BUILD_ARG(itt_sync_obj));
406#if USE_ITT_BUILD && USE_ITT_NOTIFY
407 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) {
410 __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1);
412 __kmp_itt_task_starting(itt_sync_obj);
414 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))
417 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier);
418 if (itt_sync_obj != NULL)
420 __kmp_itt_task_finished(itt_sync_obj);
389999999999999999999999999999999999999999999999999999999999991297 ::compatdrudnean class="lineno"> 470