This source file includes following definitions.
- mca_scoll_basic_barrier
- _algorithm_central_counter
- _algorithm_tournament
- _algorithm_recursive_doubling
- _algorithm_dissemination
- _algorithm_basic
- _algorithm_adaptive
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 #include "oshmem_config.h"
  14 #include <stdio.h>
  15 #include <stdlib.h>
  16 
  17 #include "oshmem/constants.h"
  18 #include "oshmem/mca/spml/spml.h"
  19 #include "oshmem/mca/scoll/scoll.h"
  20 #include "oshmem/mca/scoll/base/base.h"
  21 #include "oshmem/proc/proc.h"
  22 #include "scoll_basic.h"
  23 
  24 static int _algorithm_central_counter(struct oshmem_group_t *group,
  25                                        long *pSync);
  26 static int _algorithm_tournament(struct oshmem_group_t *group, long *pSync);
  27 static int _algorithm_recursive_doubling(struct oshmem_group_t *group,
  28                                           long *pSync);
  29 static int _algorithm_dissemination(struct oshmem_group_t *group, long *pSync);
  30 static int _algorithm_basic(struct oshmem_group_t *group, long *pSync);
  31 static int _algorithm_adaptive(struct oshmem_group_t *group, long *pSync);
  32 
  33 int mca_scoll_basic_barrier(struct oshmem_group_t *group, long *pSync, int alg)
  34 {
  35     int rc = OSHMEM_SUCCESS;
  36 
  37     
  38     if (!group || !pSync) {
  39         SCOLL_ERROR("Active set (group) of PE is not defined");
  40         rc = OSHMEM_ERR_BAD_PARAM;
  41     }
  42 
  43     if ((rc == OSHMEM_SUCCESS) && oshmem_proc_group_is_member(group)) {
  44         if (pSync) {
  45             alg = (alg == SCOLL_DEFAULT_ALG ?
  46                     mca_scoll_basic_param_barrier_algorithm : alg);
  47             switch (alg) {
  48             case SCOLL_ALG_BARRIER_CENTRAL_COUNTER:
  49                 {
  50                     rc = _algorithm_central_counter(group, pSync);
  51                     break;
  52                 }
  53             case SCOLL_ALG_BARRIER_TOURNAMENT:
  54                 {
  55                     rc = _algorithm_tournament(group, pSync);
  56                     break;
  57                 }
  58             case SCOLL_ALG_BARRIER_RECURSIVE_DOUBLING:
  59                 {
  60                     rc = _algorithm_recursive_doubling(group, pSync);
  61                     break;
  62                 }
  63             case SCOLL_ALG_BARRIER_DISSEMINATION:
  64                 {
  65                     rc = _algorithm_dissemination(group, pSync);
  66                     break;
  67                 }
  68             case SCOLL_ALG_BARRIER_BASIC:
  69                 {
  70                     rc = _algorithm_basic(group, pSync);
  71                     break;
  72                 }
  73             case SCOLL_ALG_BARRIER_ADAPTIVE:
  74                 {
  75                     rc = _algorithm_adaptive(group, pSync);
  76                     break;
  77                 }
  78             default:
  79                 {
  80                     rc = _algorithm_recursive_doubling(group, pSync);
  81                 }
  82             }
  83         } else {
  84             SCOLL_ERROR("Incorrect argument pSync");
  85             rc = OSHMEM_ERR_BAD_PARAM;
  86         }
  87     }
  88 
  89     return rc;
  90 }
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 static int _algorithm_central_counter(struct oshmem_group_t *group,
 101                                        long *pSync)
 102 {
 103     int rc = OSHMEM_SUCCESS;
 104     long value = SHMEM_SYNC_INIT;
 105     int root_id = 0;
 106     int PE_root = oshmem_proc_pe(group->proc_array[root_id]);
 107     int i = 0;
 108 
 109     SCOLL_VERBOSE(12, "[#%d] Barrier algorithm: Central Counter", group->my_pe);
 110     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 111 
 112     
 113     pSync[0] = SHMEM_SYNC_WAIT;
 114 
 115     
 116     if (PE_root == group->my_pe) {
 117         int pe_cur = 0;
 118         long wait_pe_count = 0;
 119         int* wait_pe_array = NULL;
 120 
 121         wait_pe_array = malloc(sizeof(*wait_pe_array) * group->proc_count);
 122         if (wait_pe_array) {
 123             SCOLL_VERBOSE(14, "[#%d] PE is the root", group->my_pe);
 124 
 125             wait_pe_count = group->proc_count;
 126             for (i = 0; i < group->proc_count; i++) {
 127                 wait_pe_array[i] = oshmem_proc_pe(group->proc_array[i]);
 128             }
 129             wait_pe_array[root_id] = OSHMEM_PE_INVALID;
 130             wait_pe_count--;
 131 
 132             while (wait_pe_count) {
 133                 for (i = 0; (i < group->proc_count) && (rc == OSHMEM_SUCCESS);
 134                         i++) {
 135                     pe_cur = wait_pe_array[i];
 136                     if (pe_cur != OSHMEM_PE_INVALID) {
 137                         rc = MCA_SPML_CALL(get(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, pe_cur));
 138                         if ((rc == OSHMEM_SUCCESS)
 139                                 && (value == SHMEM_SYNC_WAIT)) {
 140                             wait_pe_array[i] = OSHMEM_PE_INVALID;
 141                             wait_pe_count--;
 142                             SCOLL_VERBOSE(14,
 143                                           "[#%d] PE#%d is ready (wait list counter: %d)",
 144                                           group->my_pe, pe_cur, (int)wait_pe_count);
 145                         }
 146                     }
 147                 }
 148             }
 149 
 150             SCOLL_VERBOSE(14, "[#%d] PE signals to all", group->my_pe);
 151             value = SHMEM_SYNC_RUN;
 152             for (i = 0; (i < group->proc_count) && (rc == OSHMEM_SUCCESS);
 153                     i++) {
 154                 pe_cur = oshmem_proc_pe(group->proc_array[i]);
 155                 if (pe_cur != PE_root) {
 156                     rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, pe_cur));
 157                 }
 158             }
 159 
 160             free(wait_pe_array);
 161         } else {
 162             rc = OSHMEM_ERR_OUT_OF_RESOURCE;
 163         }
 164 
 165         
 166 
 167 
 168 
 169 
 170         MCA_SPML_CALL(quiet(oshmem_ctx_default));
 171     }
 172     
 173     else {
 174         SCOLL_VERBOSE(14,
 175                       "[#%d] PE waits for a signal from root",
 176                       group->my_pe);
 177 
 178         value = SHMEM_SYNC_RUN;
 179         rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_EQ, (void*)&value, SHMEM_LONG));
 180     }
 181 
 182     
 183     SCOLL_VERBOSE(12,
 184                   "[#%d] Restore special synchronization array",
 185                   group->my_pe);
 186     for (i = 0; i < _SHMEM_BARRIER_SYNC_SIZE; i++) {
 187         pSync[i] = _SHMEM_SYNC_VALUE;
 188     }
 189 
 190     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 191 
 192     return rc;
 193 }
 194 
 195 
 196 
 197 
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 static int _algorithm_tournament(struct oshmem_group_t *group, long *pSync)
 206 {
 207     int rc = OSHMEM_SUCCESS;
 208     int round = 0;
 209     int exit_flag = group->proc_count - 1;
 210     long value = SHMEM_SYNC_INIT;
 211     int my_id = oshmem_proc_group_find_id(group, group->my_pe);
 212     int peer_id = 0;
 213     int peer_pe = 0;
 214     int i = 0;
 215 
 216     SCOLL_VERBOSE(12, "[#%d] Barrier algorithm: Tournament", group->my_pe);
 217     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 218 
 219     
 220     pSync[0] = SHMEM_SYNC_WAIT;
 221 
 222     while (exit_flag && (rc == OSHMEM_SUCCESS)) {
 223         
 224         peer_id = my_id ^ (1 << round);
 225 
 226         
 227         exit_flag >>= 1;
 228         round++;
 229 
 230         
 231         if (peer_id >= group->proc_count)
 232             continue;
 233 
 234         if (my_id < peer_id) {
 235             pSync[0] = peer_id;
 236             value = my_id;
 237 
 238             SCOLL_VERBOSE(14, "[#%d] round = %d wait", group->my_pe, round);
 239             rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_EQ, (void*)&value, SHMEM_LONG));
 240         } else {
 241             peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 242 
 243 #if 1 
 244 
 245 
 246 
 247             do {
 248                 MCA_SPML_CALL(get(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 249             } while (value != my_id);
 250 
 251             SCOLL_VERBOSE(14,
 252                           "[#%d] round = %d signals to #%d",
 253                           group->my_pe, round, peer_pe);
 254             value = peer_id;
 255             rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 256 #else
 257             SCOLL_VERBOSE(14, "[#%d] round = %d signals to #%d", group->my_pe, round, peer_pe);
 258             do
 259             {
 260                 rc = MCA_ATOMIC_CALL(cswap((void*)pSync, (void*)&value, (const void*)&my_id, (const void*)&peer_id, sizeof(value), peer_pe));
 261             }while (value != my_id);
 262 #endif
 263             SCOLL_VERBOSE(14, "[#%d] round = %d wait", group->my_pe, round);
 264             value = SHMEM_SYNC_RUN;
 265             rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_EQ, (void*)&value, SHMEM_LONG));
 266 
 267             break;
 268         }
 269     }
 270 
 271     
 272     SCOLL_VERBOSE(12,
 273                   "[#%d] Restore special synchronization array",
 274                   group->my_pe);
 275     for (i = 0; i < _SHMEM_BARRIER_SYNC_SIZE; i++) {
 276         pSync[i] = _SHMEM_SYNC_VALUE;
 277     }
 278 
 279     
 280     if ((my_id == 0) && (rc == OSHMEM_SUCCESS)) {
 281         SCOLL_VERBOSE(14, "[#%d] signals to all", group->my_pe);
 282 
 283         value = SHMEM_SYNC_RUN;
 284         for (peer_id = 1;
 285                 (peer_id < group->proc_count) && (rc == OSHMEM_SUCCESS);
 286                 peer_id++) {
 287             peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 288             rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 289         }
 290     }
 291 
 292     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 293 
 294     return rc;
 295 }
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 static int _algorithm_recursive_doubling(struct oshmem_group_t *group,
 306                                           long *pSync)
 307 {
 308     int rc = OSHMEM_SUCCESS;
 309     int round = 0;
 310     int floor2_proc = 0;
 311     int exit_flag = 0;
 312     long value = SHMEM_SYNC_INIT;
 313     int my_id = oshmem_proc_group_find_id(group, group->my_pe);
 314     int peer_id = 0;
 315     int peer_pe = 0;
 316     int i = 0;
 317 
 318     floor2_proc = 1;
 319     i = group->proc_count;
 320     i >>= 1;
 321     while (i) {
 322         i >>= 1;
 323         floor2_proc <<= 1;
 324     }
 325 
 326     SCOLL_VERBOSE(12,
 327                   "[#%d] Barrier algorithm: Recursive Doubling",
 328                   group->my_pe);
 329     SCOLL_VERBOSE(15,
 330                   "[#%d] pSync[0] = %ld floor2_proc = %d",
 331                   group->my_pe, pSync[0], floor2_proc);
 332 
 333     if (my_id >= floor2_proc) {
 334         
 335         peer_id = my_id - floor2_proc;
 336         peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 337 
 338         SCOLL_VERBOSE(14,
 339                       "[#%d] is extra and signal to #%d",
 340                       group->my_pe, peer_pe);
 341         value = SHMEM_SYNC_WAIT;
 342         rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 343 
 344         SCOLL_VERBOSE(14, "[#%d] wait", group->my_pe);
 345         value = SHMEM_SYNC_RUN;
 346         rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_EQ, (void*)&value, SHMEM_LONG));
 347 
 348         
 349         SCOLL_VERBOSE(12,
 350                       "[#%d] Restore special synchronization array",
 351                       group->my_pe);
 352         for (i = 0; i < _SHMEM_BARRIER_SYNC_SIZE; i++) {
 353             pSync[i] = _SHMEM_SYNC_VALUE;
 354         }
 355     } else {
 356         
 357         if ((group->proc_count - floor2_proc) > my_id) {
 358             
 359             peer_id = my_id + floor2_proc;
 360             peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 361 
 362             SCOLL_VERBOSE(14,
 363                           "[#%d] wait a signal from #%d",
 364                           group->my_pe, peer_pe);
 365             value = SHMEM_SYNC_WAIT;
 366             rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_EQ, (void*)&value, SHMEM_LONG));
 367         }
 368 
 369         
 370         exit_flag = floor2_proc - 1;
 371         pSync[0] = round;
 372         while (exit_flag && (rc == OSHMEM_SUCCESS)) {
 373             
 374             peer_id = my_id ^ (1 << round);
 375 
 376             
 377             exit_flag >>= 1;
 378             round++;
 379 
 380             peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 381 
 382 #if 1 
 383 
 384 
 385 
 386             do {
 387                 MCA_SPML_CALL(get(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 388             } while (value != (round - 1));
 389 
 390             SCOLL_VERBOSE(14,
 391                           "[#%d] round = %d signals to #%d",
 392                           group->my_pe, round, peer_pe);
 393             value = round;
 394             rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 395 #else
 396             SCOLL_VERBOSE(14, "[#%d] round = %d signals to #%d", group->my_pe, round, peer_pe);
 397             {
 398                 long cond = round - 1;
 399                 do
 400                 {
 401                     rc = MCA_ATOMIC_CALL(cswap((void*)pSync, (void*)&value, (const void*)&cond, (const void*)&round, sizeof(value), peer_pe));
 402                 }while (value != (round-1));
 403             }
 404 #endif
 405 
 406             SCOLL_VERBOSE(14, "[#%d] round = %d wait", group->my_pe, round);
 407             value = round;
 408             rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_GE, (void*)&value, SHMEM_LONG));
 409         }
 410 
 411         
 412         SCOLL_VERBOSE(12,
 413                       "[#%d] Restore special synchronization array",
 414                       group->my_pe);
 415         for (i = 0; i < _SHMEM_BARRIER_SYNC_SIZE; i++) {
 416             pSync[i] = _SHMEM_SYNC_VALUE;
 417         }
 418 
 419         
 420         if ((group->proc_count - floor2_proc) > my_id) {
 421             
 422             peer_id = my_id + floor2_proc;
 423             peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 424 
 425             SCOLL_VERBOSE(14, "[#%d] signals to #%d", group->my_pe, peer_pe);
 426             value = SHMEM_SYNC_RUN;
 427             rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 428         }
 429     }
 430 
 431     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 432 
 433     return rc;
 434 }
 435 
 436 
 437 
 438 
 439 
 440 
 441 
 442 
 443 static int _algorithm_dissemination(struct oshmem_group_t *group, long *pSync)
 444 {
 445     int rc = OSHMEM_SUCCESS;
 446     int round = 0;
 447     int log2_proc = 0;
 448     long value = SHMEM_SYNC_INIT;
 449     int my_id = oshmem_proc_group_find_id(group, group->my_pe);
 450     int peer_id = 0;
 451     int peer_pe = 0;
 452     int i = 0;
 453 
 454     log2_proc = scoll_log2((unsigned long) group->proc_count);
 455 
 456     SCOLL_VERBOSE(12, "[#%d] Barrier algorithm: Dissemination", group->my_pe);
 457     SCOLL_VERBOSE(15,
 458                   "[#%d] pSync[0] = %ld floor2_proc = %d",
 459                   group->my_pe, pSync[0], log2_proc);
 460 
 461     pSync[0] = round;
 462     for (round = 0; (round <= log2_proc) && (rc == OSHMEM_SUCCESS); round++) {
 463         
 464         peer_id = (my_id + (1 << round)) % group->proc_count;
 465 
 466         peer_pe = oshmem_proc_pe(group->proc_array[peer_id]);
 467 
 468 #if 1 
 469 
 470 
 471 
 472         do {
 473             MCA_SPML_CALL(get(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 474         } while (value != round);
 475 
 476         SCOLL_VERBOSE(14,
 477                       "[#%d] round = %d signals to #%d",
 478                       group->my_pe, round, peer_pe);
 479         value = round + 1;
 480         rc = MCA_SPML_CALL(put(oshmem_ctx_default, (void*)pSync, sizeof(value), (void*)&value, peer_pe));
 481 #endif
 482 
 483         SCOLL_VERBOSE(14, "[#%d] round = %d wait", group->my_pe, round);
 484         value = round + 1;
 485         rc = MCA_SPML_CALL(wait((void*)pSync, SHMEM_CMP_GE, (void*)&value, SHMEM_LONG));
 486     }
 487 
 488     
 489     SCOLL_VERBOSE(12,
 490                   "[#%d] Restore special synchronization array",
 491                   group->my_pe);
 492     for (i = 0; i < _SHMEM_BARRIER_SYNC_SIZE; i++) {
 493         pSync[i] = _SHMEM_SYNC_VALUE;
 494     }
 495 
 496     SCOLL_VERBOSE(15, "[#%d] pSync[0] = %ld", group->my_pe, pSync[0]);
 497 
 498     return rc;
 499 }
 500 
 501 static int _algorithm_basic(struct oshmem_group_t *group, long *pSync)
 502 {
 503     int rc = OSHMEM_SUCCESS;
 504     int root_id = 0;
 505     int PE_root = oshmem_proc_pe(group->proc_array[root_id]);
 506     int i = 0;
 507 
 508     SCOLL_VERBOSE(12, "[#%d] Barrier algorithm: Basic", group->my_pe);
 509 
 510     if (PE_root != group->my_pe) {
 511         rc = MCA_SPML_CALL(send(NULL, 0, PE_root, MCA_SPML_BASE_PUT_STANDARD));
 512         if (OSHMEM_SUCCESS != rc) {
 513             return rc;
 514         }
 515 
 516         rc = MCA_SPML_CALL(recv(NULL, 0, PE_root));
 517         if (OSHMEM_SUCCESS != rc) {
 518             return rc;
 519         }
 520     }
 521 
 522     
 523 
 524     else {
 525         int pe_cur = 0;
 526 
 527         for (i = 0; (i < group->proc_count) && (rc == OSHMEM_SUCCESS); i++) {
 528             pe_cur = oshmem_proc_pe(group->proc_array[i]);
 529             if (pe_cur != PE_root) {
 530                 rc = MCA_SPML_CALL(recv(NULL, 0, pe_cur)); 
 531             }
 532             if (OSHMEM_SUCCESS != rc) {
 533                 return rc;
 534             }
 535         }
 536 
 537         for (i = 0; (i < group->proc_count) && (rc == OSHMEM_SUCCESS); i++) {
 538             pe_cur = oshmem_proc_pe(group->proc_array[i]);
 539             if (pe_cur != PE_root) {
 540                 rc = MCA_SPML_CALL(send(NULL, 0, pe_cur, MCA_SPML_BASE_PUT_STANDARD));
 541             }
 542             if (OSHMEM_SUCCESS != rc) {
 543                 return rc;
 544             }
 545         }
 546     }
 547 
 548     return rc;
 549 }
 550 
 551 static int _algorithm_adaptive(struct oshmem_group_t *group, long *pSync)
 552 {
 553     int rc = OSHMEM_SUCCESS;
 554     bool local_peers_only = true;
 555 
 556     SCOLL_VERBOSE(12, "[#%d] Barrier algorithm: Adaptive", group->my_pe);
 557 
 558     
 559     {
 560         int i = 0;
 561         int my_id = oshmem_proc_group_find_id(group, group->my_pe);
 562 
 563         for (i = 0; i < group->proc_count; i++) {
 564             if (i == my_id)
 565                 continue;
 566 
 567             if (!OPAL_PROC_ON_LOCAL_NODE(group->proc_array[i]->super.proc_flags)) {
 568                 local_peers_only = false;
 569                 break;
 570             }
 571         }
 572     }
 573 
 574     
 575 
 576 
 577 
 578     if (local_peers_only || (group->proc_count < 32)) {
 579         rc = _algorithm_basic(group, pSync);
 580     } else {
 581         rc = _algorithm_recursive_doubling(group, pSync);
 582     }
 583 
 584     return rc;
 585 }