-: 0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/coll/allgatherv.c
-: 0:Graph:allgatherv.gcno
-: 0:Data:allgatherv.gcda
-: 0:Runs:585
-: 0:Programs:151
-: 1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
-: 2:/*
-: 3: *
-: 4: * (C) 2001 by Argonne National Laboratory.
-: 5: * See COPYRIGHT in top-level directory.
-: 6: */
-: 7:
-: 8:#include "mpiimpl.h"
-: 9:
-: 10:/* -- Begin Profiling Symbol Block for routine MPI_Allgatherv */
-: 11:#if defined(HAVE_PRAGMA_WEAK)
-: 12:#pragma weak MPI_Allgatherv = PMPI_Allgatherv
-: 13:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
-: 14:#pragma _HP_SECONDARY_DEF PMPI_Allgatherv MPI_Allgatherv
-: 15:#elif defined(HAVE_PRAGMA_CRI_DUP)
-: 16:#pragma _CRI duplicate MPI_Allgatherv as PMPI_Allgatherv
-: 17:#endif
-: 18:/* -- End Profiling Symbol Block */
-: 19:
-: 20:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
-: 21: the MPI routines */
-: 22:#ifndef MPICH_MPI_FROM_PMPI
-: 23:#undef MPI_Allgatherv
-: 24:#define MPI_Allgatherv PMPI_Allgatherv
-: 25:
-: 26:/* This is the default implementation of allgatherv. The algorithm is:
-: 27:
-: 28: Algorithm: MPI_Allgatherv
-: 29:
-: 30: For short messages and non-power-of-two no. of processes, we use
-: 31: the algorithm from the Jehoshua Bruck et al IEEE TPDS Nov 97
-: 32: paper. It is a variant of the disemmination algorithm for
-: 33: barrier. It takes ceiling(lg p) steps.
-: 34:
-: 35: Cost = lgp.alpha + n.((p-1)/p).beta
-: 36: where n is total size of data gathered on each process.
-: 37:
-: 38: For short or medium-size messages and power-of-two no. of
-: 39: processes, we use the recursive doubling algorithm.
-: 40:
-: 41: Cost = lgp.alpha + n.((p-1)/p).beta
-: 42:
-: 43: TODO: On TCP, we may want to use recursive doubling instead of the Bruck
-: 44: algorithm in all cases because of the pairwise-exchange property of
-: 45: recursive doubling (see Benson et al paper in Euro PVM/MPI
-: 46: 2003).
-: 47:
-: 48: For long messages or medium-size messages and non-power-of-two
-: 49: no. of processes, we use a ring algorithm. In the first step, each
-: 50: process i sends its contribution to process i+1 and receives
-: 51: the contribution from process i-1 (with wrap-around). From the
-: 52: second step onwards, each process i forwards to process i+1 the
-: 53: data it received from process i-1 in the previous step. This takes
-: 54: a total of p-1 steps.
-: 55:
-: 56: Cost = (p-1).alpha + n.((p-1)/p).beta
-: 57:
-: 58: Possible improvements:
-: 59:
-: 60: End Algorithm: MPI_Allgatherv
-: 61:*/
-: 62:
-: 63:/* begin:nested */
-: 64:/* not declared static because a machine-specific function may call this one
-: 65: in some cases */
-: 66:int MPIR_Allgatherv (
-: 67: void *sendbuf,
-: 68: int sendcount,
-: 69: MPI_Datatype sendtype,
-: 70: void *recvbuf,
-: 71: int *recvcounts,
-: 72: int *displs,
-: 73: MPI_Datatype recvtype,
-: 74: MPID_Comm *comm_ptr )
16926: 75:{
-: 76: static const char FCNAME[] = "MPIR_Allgatherv";
-: 77: MPI_Comm comm;
-: 78: int comm_size, rank, j, i, left, right;
16926: 79: int mpi_errno = MPI_SUCCESS;
-: 80: MPI_Status status;
-: 81: MPI_Aint recvbuf_extent, recvtype_extent, recvtype_true_extent,
-: 82: recvtype_true_lb;
-: 83: int curr_cnt, send_cnt, dst, total_count, recvtype_size, pof2, src, rem;
-: 84: int recv_cnt, comm_size_is_pof2;
-: 85: void *tmp_buf;
-: 86: int mask, dst_tree_root, my_tree_root, is_homogeneous, position,
-: 87: send_offset, recv_offset, last_recv_cnt, nprocs_completed, k,
-: 88: offset, tmp_mask, tree_root;
-: 89:#ifdef MPID_HAS_HETERO
-: 90: int tmp_buf_size, nbytes;
-: 91:#endif
-: 92:
16926: 93: comm = comm_ptr->handle;
16926: 94: comm_size = comm_ptr->local_size;
16926: 95: rank = comm_ptr->rank;
-: 96:
16926: 97: total_count = 0;
83416: 98: for (i=0; i<comm_size; i++)
66490: 99: total_count += recvcounts[i];
-: 100:
16926: 101: if (total_count == 0) return MPI_SUCCESS;
-: 102:
16732: 103: MPID_Datatype_get_extent_macro( recvtype, recvtype_extent );
16732: 104: MPID_Datatype_get_size_macro(recvtype, recvtype_size);
-: 105:
-: 106: /* check if comm_size is a power of two */
16732: 107: pof2 = 1;
66494: 108: while (pof2 < comm_size)
33030: 109: pof2 *= 2;
16732: 110: if (pof2 == comm_size)
11706: 111: comm_size_is_pof2 = 1;
-: 112: else
5026: 113: comm_size_is_pof2 = 0;
-: 114:
-: 115: /* check if multiple threads are calling this collective function */
-: 116: MPIDU_ERR_CHECK_MULTIPLE_THREADS_ENTER( comm_ptr );
-: 117:
16732: 118: if ((total_count*recvtype_size < MPIR_ALLGATHER_LONG_MSG) &&
-: 119: (comm_size_is_pof2 == 1)) {
-: 120: /* Short or medium size message and power-of-two no. of processes. Use
-: 121: * recursive doubling algorithm */
-: 122:
11130: 123: is_homogeneous = 1;
-: 124:#ifdef MPID_HAS_HETERO
-: 125: if (comm_ptr->is_hetero)
-: 126: is_homogeneous = 0;
-: 127:#endif
-: 128:
11130: 129: if (is_homogeneous) {
-: 130: /* need to receive contiguously into tmp_buf because
-: 131: displs could make the recvbuf noncontiguous */
-: 132:
11130: 133: mpi_errno = NMPI_Type_get_true_extent(recvtype, &recvtype_true_lb,
-: 134: &recvtype_true_extent);
|
-: 135: /* --BEGIN ERROR HANDLING-- */
11130: 136: if (mpi_errno)
-: 137: {
#####: 138: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 139: return mpi_errno;
-: 140: }
-: 141: /* --END ERROR HANDLING-- */
-: 142:
-: 143: MPID_Ensure_Aint_fits_in_pointer(total_count *
-: 144: (MPIR_MAX(recvtype_true_extent, recvtype_extent)));
|
11130: 145: tmp_buf = MPIU_Malloc(total_count*(MPIR_MAX(recvtype_true_extent,recvtype_extent)));
|
-: 146: /* --BEGIN ERROR HANDLING-- */
11130: 147: if (!tmp_buf)
-: 148: {
#####: 149: mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);
#####: 150: return mpi_errno;
-: 151: }
-: 152: /* --END ERROR HANDLING-- */
-: 153:
-: 154: /* adjust for potential negative lower bound in datatype */
|
11130: 155: tmp_buf = (void *)((char*)tmp_buf - recvtype_true_lb);
-: 156:
-: 157: /* copy local data into right location in tmp_buf */
11130: 158: position = 0;
11130: 159: for (i=0; i<rank; i++) position += recvcounts[i];
11130: 160: if (sendbuf != MPI_IN_PLACE)
-: 161: {
11026: 162: mpi_errno = MPIR_Localcopy(sendbuf, sendcount, sendtype,
-: 163: ((char *)tmp_buf + position*
-: 164: recvtype_extent),
-: 165: recvcounts[rank], recvtype);
-: 166: }
-: 167: else
-: 168: {
-: 169: /* if in_place specified, local data is found in recvbuf */
104: 170: mpi_errno = MPIR_Localcopy(((char *)recvbuf +
-: 171: displs[rank]*recvtype_extent),
-: 172: recvcounts[rank], recvtype,
-: 173: ((char *)tmp_buf + position*
-: 174: recvtype_extent),
-: 175: recvcounts[rank], recvtype);
-: 176: }
|
-: 177: /* --BEGIN ERROR HANDLING-- */
11130: 178: if (mpi_errno)
-: 179: {
#####: 180: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 181: return mpi_errno;
-: 182: }
-: 183: /* --END ERROR HANDLING-- */
-: 184:
|
11130: 185: curr_cnt = recvcounts[rank];
-: 186:
11130: 187: mask = 0x1;
11130: 188: i = 0;
41366: 189: while (mask < comm_size) {
19106: 190: dst = rank ^ mask;
-: 191:
-: 192: /* find offset into send and recv buffers. zero out
-: 193: the least significant "i" bits of rank and dst to
-: 194: find root of src and dst subtrees. Use ranks of
-: 195: roots as index to send from and recv into buffer */
-: 196:
19106: 197: dst_tree_root = dst >> i;
19106: 198: dst_tree_root <<= i;
-: 199:
19106: 200: my_tree_root = rank >> i;
19106: 201: my_tree_root <<= i;
-: 202:
19106: 203: if (dst < comm_size) {
19106: 204: send_offset = 0;
42841: 205: for (j=0; j<my_tree_root; j++)
23735: 206: send_offset += recvcounts[j];
-: 207:
19106: 208: recv_offset = 0;
42841: 209: for (j=0; j<dst_tree_root; j++)
23735: 210: recv_offset += recvcounts[j];
-: 211:
19106: 212: mpi_errno = MPIC_Sendrecv(((char *)tmp_buf + send_offset * recvtype_extent),
-: 213: curr_cnt, recvtype, dst,
-: 214: MPIR_ALLGATHERV_TAG,
-: 215: ((char *)tmp_buf + recv_offset * recvtype_extent),
-: 216: total_count - recv_offset, recvtype, dst,
-: 217: MPIR_ALLGATHERV_TAG,
-: 218: comm, &status);
-: 219: /* for convenience, recv is posted for a bigger amount
-: 220: than will be sent */
|
-: 221: /* --BEGIN ERROR HANDLING-- */
19106: 222: if (mpi_errno)
-: 223: {
#####: 224: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 225: return mpi_errno;
-: 226: }
-: 227: /* --END ERROR HANDLING-- */
-: 228:
|
19106: 229: NMPI_Get_count(&status, recvtype, &last_recv_cnt);
19106: 230: curr_cnt += last_recv_cnt;
-: 231: }
-: 232:
-: 233: /* if some processes in this process's subtree in this step
-: 234: did not have any destination process to communicate with
-: 235: because of non-power-of-two, we need to send them the
-: 236: data that they would normally have received from those
-: 237: processes. That is, the haves in this subtree must send to
-: 238: the havenots. We use a logarithmic
-: 239: recursive-halfing algorithm for this. */
-: 240:
-: 241: /* This part of the code will not currently be
-: 242: executed because we are not using recursive
-: 243: doubling for non power of two. Mark it as experimental
-: 244: so that it doesn't show up as red in the coverage
-: 245: tests. */
-: 246:
|
-: 247: /* --BEGIN EXPERIMENTAL-- */
19106: 248: if (dst_tree_root + mask > comm_size) {
#####: 249: nprocs_completed = comm_size - my_tree_root - mask;
-: 250: /* nprocs_completed is the number of processes in this
-: 251: subtree that have all the data. Send data to others
-: 252: in a tree fashion. First find root of current tree
-: 253: that is being divided into two. k is the number of
-: 254: least-significant bits in this process's rank that
-: 255: must be zeroed out to find the rank of the root */
#####: 256: j = mask;
#####: 257: k = 0;
#####: 258: while (j) {
#####: 259: j >>= 1;
#####: 260: k++;
-: 261: }
#####: 262: k--;
-: 263:
#####: 264: tmp_mask = mask >> 1;
-: 265:
#####: 266: while (tmp_mask) {
#####: 267: dst = rank ^ tmp_mask;
-: 268:
#####: 269: tree_root = rank >> k;
#####: 270: tree_root <<= k;
-: 271:
-: 272: /* send only if this proc has data and destination
-: 273: doesn't have data. at any step, multiple processes
-: 274: can send if they have the data */
#####: 275: if ((dst > rank) &&
-: 276: (rank < tree_root + nprocs_completed)
-: 277: && (dst >= tree_root + nprocs_completed)) {
-: 278:
#####: 279: offset = 0;
#####: 280: for (j=0; j<(my_tree_root+mask); j++)
#####: 281: offset += recvcounts[j];
#####: 282: offset *= recvtype_extent;
-: 283:
#####: 284: mpi_errno = MPIC_Send(((char *)tmp_buf + offset),
-: 285: last_recv_cnt,
-: 286: recvtype, dst,
-: 287: MPIR_ALLGATHERV_TAG, comm);
-: 288: /* last_recv_cnt was set in the previous
-: 289: receive. that's the amount of data to be
-: 290: sent now. */
-: 291: /* --BEGIN ERROR HANDLING-- */
#####: 292: if (mpi_errno)
-: 293: {
#####: 294: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 295: return mpi_errno;
-: 296: }
-: 297: /* --END ERROR HANDLING-- */
-: 298: }
-: 299: /* recv only if this proc. doesn't have data and sender
-: 300: has data */
#####: 301: else if ((dst < rank) &&
-: 302: (dst < tree_root + nprocs_completed) &&
-: 303: (rank >= tree_root + nprocs_completed)) {
-: 304:
#####: 305: offset = 0;
#####: 306: for (j=0; j<(my_tree_root+mask); j++)
#####: 307: offset += recvcounts[j];
-: 308:
#####: 309: mpi_errno = MPIC_Recv(((char *)tmp_buf + offset * recvtype_extent),
-: 310: total_count - offset, recvtype,
-: 311: dst, MPIR_ALLGATHERV_TAG,
-: 312: comm, &status);
-: 313: /* --BEGIN ERROR HANDLING-- */
#####: 314: if (mpi_errno)
-: 315: {
#####: 316: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 317: return mpi_errno;
-: 318: }
-: 319: /* --END ERROR HANDLING-- */
-: 320: /* for convenience, recv is posted for a
-: 321: bigger amount than will be sent */
-: 322:
#####: 323: NMPI_Get_count(&status, recvtype, &last_recv_cnt);
#####: 324: curr_cnt += last_recv_cnt;
-: 325: }
#####: 326: tmp_mask >>= 1;
#####: 327: k--;
-: 328: }
-: 329: }
-: 330: /* --END EXPERIMENTAL-- */
-: 331:
|
19106: 332: mask <<= 1;
19106: 333: i++;
-: 334: }
-: 335:
-: 336: /* copy data from tmp_buf to recvbuf */
11130: 337: position = 0;
50682: 338: for (j=0; j<comm_size; j++) {
39552: 339: if ((sendbuf != MPI_IN_PLACE) || (j != rank)) {
-: 340: /* not necessary to copy if in_place and
-: 341: j==rank. otherwise copy. */
39448: 342: MPIR_Localcopy(((char *)tmp_buf + position*recvtype_extent),
-: 343: recvcounts[j], recvtype,
-: 344: ((char *)recvbuf + displs[j]*recvtype_extent),
-: 345: recvcounts[j], recvtype);
-: 346: }
39552: 347: position += recvcounts[j];
-: 348: }
-: 349:
11130: 350: MPIU_Free((char *)tmp_buf+recvtype_true_lb);
-: 351: }
-: 352:
-: 353:#ifdef MPID_HAS_HETERO
-: 354: else {
-: 355: /* heterogeneous. need to use temp. buffer. */
-: 356: NMPI_Pack_size(total_count, recvtype, comm, &tmp_buf_size);
-: 357: tmp_buf = MPIU_Malloc(tmp_buf_size);
|
-: 358: /* --BEGIN ERROR HANDLING-- */
-: 359: if (!tmp_buf)
-: 360: {
-: 361: mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);
-: 362: return mpi_errno;
-: 363: }
-: 364: /* --END ERROR HANDLING-- */
-: 365:
-: 366: /* calculate the value of nbytes, the number of bytes in packed
-: 367: representation corresponding to a single recvtype. Since
-: 368: MPI_Pack_size returns only an upper bound on
-: 369: the size, to get the real size we actually pack some data
-: 370: into tmp_buf and see by how much 'position' is incremented. */
-: 371:
-: 372: position = 0;
-: 373: NMPI_Pack(recvbuf, 1, recvtype, tmp_buf, tmp_buf_size,
-: 374: &position, comm);
-: 375: nbytes = position;
-: 376:
-: 377: /* pack local data into right location in tmp_buf */
-: 378: position = 0;
-: 379: for (i=0; i<rank; i++) position += recvcounts[i];
-: 380: position *= nbytes;
-: 381:
-: 382: if (sendbuf != MPI_IN_PLACE) {
-: 383: NMPI_Pack(sendbuf, sendcount, sendtype, tmp_buf,
-: 384: tmp_buf_size, &position, comm);
-: 385: }
-: 386: else {
-: 387: /* if in_place specified, local data is found in recvbuf */
-: 388: NMPI_Pack(((char *)recvbuf + displs[rank]*recvtype_extent),
-: 389: recvcounts[rank], recvtype, tmp_buf,
-: 390: tmp_buf_size, &position, comm);
-: 391: }
-: 392:
-: 393: curr_cnt = recvcounts[rank]*nbytes;
-: 394:
-: 395: mask = 0x1;
-: 396: i = 0;
-: 397: while (mask < comm_size) {
-: 398: dst = rank ^ mask;
-: 399:
-: 400: /* find offset into send and recv buffers. zero out
-: 401: the least significant "i" bits of rank and dst to
-: 402: find root of src and dst subtrees. Use ranks of
-: 403: roots as index to send from and recv into buffer. */
-: 404:
-: 405: dst_tree_root = dst >> i;
-: 406: dst_tree_root <<= i;
-: 407:
-: 408: my_tree_root = rank >> i;
-: 409: my_tree_root <<= i;
-: 410:
-: 411: send_offset = 0;
-: 412: for (j=0; j<my_tree_root; j++)
-: 413: send_offset += recvcounts[j];
-: 414: send_offset *= nbytes;
-: 415:
-: 416: recv_offset = 0;
-: 417: for (j=0; j<dst_tree_root; j++)
-: 418: recv_offset += recvcounts[j];
-: 419: recv_offset *= nbytes;
-: 420:
-: 421: if (dst < comm_size) {
-: 422: mpi_errno = MPIC_Sendrecv(((char *)tmp_buf + send_offset),
-: 423: curr_cnt, MPI_BYTE, dst,
-: 424: MPIR_ALLGATHERV_TAG,
-: 425: ((char *)tmp_buf + recv_offset),
-: 426: tmp_buf_size-recv_offset, MPI_BYTE, dst,
-: 427: MPIR_ALLGATHERV_TAG, comm, &status);
-: 428: /* for convenience, recv is posted for a bigger amount
-: 429: than will be sent */
-: 430: /* --BEGIN ERROR HANDLING-- */
-: 431: if (mpi_errno)
-: 432: {
-: 433: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
-: 434: return mpi_errno;
-: 435: }
-: 436: /* --END ERROR HANDLING-- */
-: 437:
-: 438: NMPI_Get_count(&status, MPI_BYTE, &last_recv_cnt);
-: 439: curr_cnt += last_recv_cnt;
-: 440: }
-: 441:
-: 442: /* if some processes in this process's subtree in this step
-: 443: did not have any destination process to communicate with
-: 444: because of non-power-of-two, we need to send them the
-: 445: data that they would normally have received from those
-: 446: processes. That is, the haves in this subtree must send to
-: 447: the havenots. We use a logarithmic recursive-halfing algorithm
-: 448: for this. */
-: 449:
-: 450: if (dst_tree_root + mask > comm_size) {
-: 451: nprocs_completed = comm_size - my_tree_root - mask;
-: 452: /* nprocs_completed is the number of processes in this
-: 453: subtree that have all the data. Send data to others
-: 454: in a tree fashion. First find root of current tree
-: 455: that is being divided into two. k is the number of
-: 456: least-significant bits in this process's rank that
-: 457: must be zeroed out to find the rank of the root */
-: 458: j = mask;
-: 459: k = 0;
-: 460: while (j) {
-: 461: j >>= 1;
-: 462: k++;
-: 463: }
-: 464: k--;
-: 465:
-: 466: offset = 0;
-: 467: for (j=0; j<(my_tree_root+mask); j++)
-: 468: offset += recvcounts[j];
-: 469: offset *= nbytes;
-: 470: tmp_mask = mask >> 1;
-: 471:
-: 472: while (tmp_mask) {
-: 473: dst = rank ^ tmp_mask;
-: 474:
-: 475: tree_root = rank >> k;
-: 476: tree_root <<= k;
-: 477:
-: 478: /* send only if this proc has data and destination
-: 479: doesn't have data. at any step, multiple processes
-: 480: can send if they have the data */
-: 481: if ((dst > rank) &&
-: 482: (rank < tree_root + nprocs_completed)
-: 483: && (dst >= tree_root + nprocs_completed)) {
-: 484:
-: 485: mpi_errno = MPIC_Send(((char *)tmp_buf + offset),
-: 486: last_recv_cnt, MPI_BYTE,
-: 487: dst, MPIR_ALLGATHERV_TAG,
-: 488: comm);
-: 489: /* last_recv_cnt was set in the previous
-: 490: receive. that's the amount of data to be
-: 491: sent now. */
-: 492: /* --BEGIN ERROR HANDLING-- */
-: 493: if (mpi_errno)
-: 494: {
-: 495: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
-: 496: return mpi_errno;
-: 497: }
-: 498: /* --END ERROR HANDLING-- */
-: 499: }
-: 500: /* recv only if this proc. doesn't have data and sender
-: 501: has data */
-: 502: else if ((dst < rank) &&
-: 503: (dst < tree_root + nprocs_completed) &&
-: 504: (rank >= tree_root + nprocs_completed)) {
-: 505: mpi_errno = MPIC_Recv(((char *)tmp_buf + offset),
-: 506: tmp_buf_size-offset, MPI_BYTE,
-: 507: dst,
-: 508: MPIR_ALLGATHERV_TAG,
-: 509: comm, &status);
-: 510: /* for convenience, recv is posted for a bigger amount
-: 511: than will be sent */
-: 512: /* --BEGIN ERROR HANDLING-- */
-: 513: if (mpi_errno)
-: 514: {
-: 515: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
-: 516: return mpi_errno;
-: 517: }
-: 518: /* --END ERROR HANDLING-- */
-: 519: NMPI_Get_count(&status, MPI_BYTE, &last_recv_cnt);
-: 520: curr_cnt += last_recv_cnt;
-: 521: }
-: 522: tmp_mask >>= 1;
-: 523: k--;
-: 524: }
-: 525: }
-: 526: mask <<= 1;
-: 527: i++;
-: 528: }
-: 529:
-: 530: position = 0;
-: 531: for (j=0; j<comm_size; j++) {
-: 532: if ((sendbuf != MPI_IN_PLACE) || (j != rank)) {
-: 533: /* not necessary to unpack if in_place and
-: 534: j==rank. otherwise unpack. */
-: 535: NMPI_Unpack(tmp_buf, tmp_buf_size, &position,
-: 536: ((char *)recvbuf + displs[j]*recvtype_extent),
-: 537: recvcounts[j], recvtype, comm);
-: 538: }
-: 539: }
-: 540:
-: 541: MPIU_Free(tmp_buf);
-: 542: }
-: 543:#endif /* MPID_HAS_HETERO */
-: 544:
-: 545: }
-: 546:
|
5602: 547: else if (total_count*recvtype_size < MPIR_ALLGATHER_SHORT_MSG) {
-: 548: /* Short message and non-power-of-two no. of processes. Use
-: 549: * Bruck algorithm (see description above). */
-: 550:
-: 551: /* allocate a temporary buffer of the same size as recvbuf. */
-: 552:
-: 553: /* get true extent of recvtype */
4024: 554: mpi_errno = NMPI_Type_get_true_extent(recvtype,
-: 555: &recvtype_true_lb,
-: 556: &recvtype_true_extent);
|
-: 557: /* --BEGIN ERROR HANDLING-- */
4024: 558: if (mpi_errno)
-: 559: {
#####: 560: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 561: return mpi_errno;
-: 562: }
-: 563: /* --END ERROR HANDLING-- */
-: 564:
-: 565: MPID_Ensure_Aint_fits_in_pointer(total_count *
-: 566: MPIR_MAX(recvtype_true_extent, recvtype_extent));
|
4024: 567: recvbuf_extent = total_count *
-: 568: (MPIR_MAX(recvtype_true_extent, recvtype_extent));
-: 569:
4024: 570: tmp_buf = MPIU_Malloc(recvbuf_extent);
|
-: 571: /* --BEGIN ERROR HANDLING-- */
4024: 572: if (!tmp_buf) {
#####: 573: mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0 );
#####: 574: return mpi_errno;
-: 575: }
-: 576: /* --END ERROR HANDLING-- */
-: 577:
-: 578: /* adjust for potential negative lower bound in datatype */
|
4024: 579: tmp_buf = (void *)((char*)tmp_buf - recvtype_true_lb);
-: 580:
-: 581: /* copy local data to the top of tmp_buf */
4024: 582: if (sendbuf != MPI_IN_PLACE) {
3427: 583: mpi_errno = MPIR_Localcopy (sendbuf, sendcount, sendtype,
-: 584: tmp_buf, recvcounts[rank], recvtype);
|
-: 585: /* --BEGIN ERROR HANDLING-- */
3427: 586: if (mpi_errno)
-: 587: {
#####: 588: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 589: return mpi_errno;
-: 590: }
-: 591: /* --END ERROR HANDLING-- */
-: 592: }
-: 593: else {
|
597: 594: mpi_errno = MPIR_Localcopy(((char *)recvbuf +
-: 595: displs[rank]*recvtype_extent),
-: 596: recvcounts[rank], recvtype,
-: 597: tmp_buf, recvcounts[rank], recvtype);
|
-: 598: /* --BEGIN ERROR HANDLING-- */
597: 599: if (mpi_errno)
-: 600: {
#####: 601: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 602: return mpi_errno;
-: 603: }
-: 604: /* --END ERROR HANDLING-- */
-: 605: }
-: 606:
-: 607: /* do the first \floor(\lg p) steps */
-: 608:
|
4024: 609: curr_cnt = recvcounts[rank];
4024: 610: pof2 = 1;
14080: 611: while (pof2 <= comm_size/2) {
6032: 612: src = (rank + pof2) % comm_size;
6032: 613: dst = (rank - pof2 + comm_size) % comm_size;
-: 614:
6032: 615: mpi_errno = MPIC_Sendrecv(tmp_buf, curr_cnt, recvtype, dst,
-: 616: MPIR_ALLGATHERV_TAG,
-: 617: ((char *)tmp_buf + curr_cnt*recvtype_extent),
-: 618: total_count - curr_cnt, recvtype,
-: 619: src, MPIR_ALLGATHERV_TAG, comm, &status);
|
-: 620: /* --BEGIN ERROR HANDLING-- */
6032: 621: if (mpi_errno)
-: 622: {
#####: 623: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 624: return mpi_errno;
-: 625: }
-: 626: /* --END ERROR HANDLING-- */
-: 627:
|
6032: 628: NMPI_Get_count(&status, recvtype, &recv_cnt);
6032: 629: curr_cnt += recv_cnt;
-: 630:
6032: 631: pof2 *= 2;
-: 632: }
-: 633:
-: 634: /* if comm_size is not a power of two, one more step is needed */
-: 635:
4024: 636: rem = comm_size - pof2;
4024: 637: if (rem) {
4024: 638: src = (rank + pof2) % comm_size;
4024: 639: dst = (rank - pof2 + comm_size) % comm_size;
-: 640:
4024: 641: send_cnt = 0;
9094: 642: for (i=0; i<rem; i++)
5070: 643: send_cnt += recvcounts[(rank+i)%comm_size];
-: 644:
4024: 645: mpi_errno = MPIC_Sendrecv(tmp_buf, send_cnt, recvtype,
-: 646: dst, MPIR_ALLGATHERV_TAG,
-: 647: ((char *)tmp_buf + curr_cnt*recvtype_extent),
-: 648: total_count - curr_cnt, recvtype,
-: 649: src, MPIR_ALLGATHERV_TAG, comm,
-: 650: MPI_STATUS_IGNORE);
|
-: 651: /* --BEGIN ERROR HANDLING-- */
4024: 652: if (mpi_errno)
-: 653: {
#####: 654: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 655: return mpi_errno;
-: 656: }
-: 657: /* --END ERROR HANDLING-- */
-: 658: }
-: 659:
-: 660: /* Rotate blocks in tmp_buf down by (rank) blocks and store
-: 661: * result in recvbuf. */
-: 662:
|
4024: 663: send_cnt = 0;
15401: 664: for (i=0; i < (comm_size-rank); i++) {
11377: 665: j = (rank+i)%comm_size;
11377: 666: mpi_errno = MPIR_Localcopy((char *)tmp_buf + send_cnt*recvtype_extent,
-: 667: recvcounts[j], recvtype,
-: 668: (char *)recvbuf + displs[j]*recvtype_extent,
-: 669: recvcounts[j], recvtype);
|
-: 670: /* --BEGIN ERROR HANDLING-- */
11377: 671: if (mpi_errno)
-: 672: {
#####: 673: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 674: return mpi_errno;
-: 675: }
-: 676: /* --END ERROR HANDLING-- */
|
11377: 677: send_cnt += recvcounts[j];
-: 678: }
-: 679:
11377: 680: for (i=0; i<rank; i++) {
7353: 681: mpi_errno = MPIR_Localcopy((char *)tmp_buf + send_cnt*recvtype_extent,
-: 682: recvcounts[i], recvtype,
-: 683: (char *)recvbuf + displs[i]*recvtype_extent,
-: 684: recvcounts[i], recvtype);
|
-: 685: /* --BEGIN ERROR HANDLING-- */
7353: 686: if (mpi_errno)
-: 687: {
#####: 688: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 689: return mpi_errno;
-: 690: }
-: 691: /* --END ERROR HANDLING-- */
|
7353: 692: send_cnt += recvcounts[i];
-: 693: }
-: 694:
4024: 695: MPIU_Free((char*)tmp_buf + recvtype_true_lb);
-: 696: }
-: 697: else {
-: 698: /* long message or medium-size message and non-power-of-two
-: 699: * no. of processes. Use ring algorithm. */
1578: 700: char * sbuf = NULL, * rbuf = NULL;
-: 701: int soffset, roffset;
-: 702: int torecv, tosend, min;
-: 703: int sendnow, recvnow;
-: 704: int sindex, rindex;
-: 705:
1578: 706: if (sendbuf != MPI_IN_PLACE) {
-: 707: /* First, load the "local" version in the recvbuf. */
1369: 708: mpi_errno = MPIR_Localcopy(sendbuf, sendcount, sendtype,
-: 709: ((char *)recvbuf + displs[rank]*recvtype_extent),
-: 710: recvcounts[rank], recvtype);
|
-: 711: /* --BEGIN ERROR HANDLING-- */
1369: 712: if (mpi_errno)
-: 713: {
#####: 714: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 715: return mpi_errno;
-: 716: }
-: 717: /* --END ERROR HANDLING-- */
-: 718: }
-: 719:
|
1578: 720: left = (comm_size + rank - 1) % comm_size;
1578: 721: right = (rank + 1) % comm_size;
-: 722:
1578: 723: torecv = total_count - recvcounts[rank];
1578: 724: tosend = total_count - recvcounts[right];
-: 725:
1578: 726: min = recvcounts[0];
7714: 727: for (i = 1; i < comm_size; i++)
6136: 728: if (min > recvcounts[i])
1320: 729: min = recvcounts[i];
1578: 730: if (min * recvtype_extent < MPIR_ALLGATHERV_PIPELINE_MSGSIZE)
714: 731: min = MPIR_ALLGATHERV_PIPELINE_MSGSIZE / recvtype_extent;
-: 732: /* Handle the case where the datatype extent is larger than
-: 733: * the pipeline size. */
1578: 734: if (!min)
|
#####: 735: min = 1;
-: 736:
|
1578: 737: sindex = rank;
1578: 738: rindex = left;
1578: 739: soffset = 0;
1578: 740: roffset = 0;
17132: 741: while (tosend || torecv) { /* While we have data to send or receive */
13976: 742: sendnow = ((recvcounts[sindex] - soffset) > min) ? min : (recvcounts[sindex] - soffset);
13976: 743: recvnow = ((recvcounts[rindex] - roffset) > min) ? min : (recvcounts[rindex] - roffset);
13976: 744: sbuf = (char *)recvbuf + ((displs[sindex] + soffset) * recvtype_extent);
13976: 745: rbuf = (char *)recvbuf + ((displs[rindex] + roffset) * recvtype_extent);
-: 746:
-: 747: /* Protect against wrap-around of indices */
13976: 748: if (!tosend)
1710: 749: sendnow = 0;
13976: 750: if (!torecv)
1710: 751: recvnow = 0;
-: 752:
-: 753: /* Communicate */
13976: 754: if (!sendnow && !recvnow) {
-: 755: /* Don't do anything. This case is possible if two
-: 756: * consecutive processes contribute 0 bytes each. */
-: 757: }
13886: 758: else if (!sendnow) { /* If there's no data to send, just do a recv call */
1870: 759: mpi_errno = MPIC_Recv(rbuf, recvnow, recvtype, left, MPIR_ALLGATHERV_TAG, comm, &status);
|
-: 760: /* --BEGIN ERROR HANDLING-- */
1870: 761: if (mpi_errno)
-: 762: {
#####: 763: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 764: return mpi_errno;
-: 765: }
-: 766: /* --END ERROR HANDLING-- */
|
1870: 767: torecv -= recvnow;
-: 768: }
12016: 769: else if (!recvnow) { /* If there's no data to receive, just do a send call */
1870: 770: mpi_errno = MPIC_Send(sbuf, sendnow, recvtype, right, MPIR_ALLGATHERV_TAG, comm);
|
-: 771: /* --BEGIN ERROR HANDLING-- */
1870: 772: if (mpi_errno)
-: 773: {
#####: 774: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 775: return mpi_errno;
-: 776: }
-: 777: /* --END ERROR HANDLING-- */
|
1870: 778: tosend -= sendnow;
-: 779: }
-: 780: else { /* There's data to be sent and received */
10146: 781: mpi_errno = MPIC_Sendrecv(sbuf, sendnow, recvtype, right, MPIR_ALLGATHERV_TAG,
-: 782: rbuf, recvnow, recvtype, left, MPIR_ALLGATHERV_TAG,
-: 783: comm, &status);
|
-: 784: /* --BEGIN ERROR HANDLING-- */
10146: 785: if (mpi_errno)
-: 786: {
#####: 787: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 788: return mpi_errno;
-: 789: }
-: 790: /* --END ERROR HANDLING-- */
|
10146: 791: tosend -= sendnow;
10146: 792: torecv -= recvnow;
-: 793: }
-: 794:
13976: 795: soffset += sendnow;
13976: 796: roffset += recvnow;
13976: 797: if (soffset == recvcounts[sindex]) {
5986: 798: soffset = 0;
5986: 799: sindex = (sindex + comm_size - 1) % comm_size;
-: 800: }
13976: 801: if (roffset == recvcounts[rindex]) {
6136: 802: roffset = 0;
6136: 803: rindex = (rindex + comm_size - 1) % comm_size;
-: 804: }
-: 805: }
-: 806: }
-: 807:
-: 808: /* check if multiple threads are calling this collective function */
-: 809: MPIDU_ERR_CHECK_MULTIPLE_THREADS_EXIT( comm_ptr );
-: 810:
16732: 811: return (mpi_errno);
-: 812:}
-: 813:/* end:nested */
-: 814:
-: 815:/* begin:nested */
-: 816:/* not declared static because a machine-specific function may call this one in some cases */
-: 817:int MPIR_Allgatherv_inter (
-: 818: void *sendbuf,
-: 819: int sendcount,
-: 820: MPI_Datatype sendtype,
-: 821: void *recvbuf,
-: 822: int *recvcounts,
-: 823: int *displs,
-: 824: MPI_Datatype recvtype,
-: 825: MPID_Comm *comm_ptr )
2880: 826:{
-: 827:/* Intercommunicator Allgatherv.
-: 828: This is done differently from the intercommunicator allgather
-: 829: because we don't have all the information to do a local
-: 830: intracommunictor gather (sendcount can be different on each
-: 831: process). Therefore, we do the following:
-: 832: Each group first does an intercommunicator gather to rank 0
-: 833: and then does an intracommunicator broadcast.
-: 834:*/
-: 835: static const char FCNAME[] = "MPIR_Allgatherv_inter";
-: 836: int remote_size, mpi_errno, root, rank;
2880: 837: MPID_Comm *newcomm_ptr = NULL;
-: 838: MPI_Datatype newtype;
-: 839:
2880: 840: remote_size = comm_ptr->remote_size;
2880: 841: rank = comm_ptr->rank;
-: 842:
-: 843: /* first do an intercommunicator gatherv from left to right group,
-: 844: then from right to left group */
2880: 845: if (comm_ptr->is_low_group) {
-: 846: /* gatherv from right group */
992: 847: root = (rank == 0) ? MPI_ROOT : MPI_PROC_NULL;
992: 848: mpi_errno = MPIR_Gatherv(sendbuf, sendcount, sendtype, recvbuf,
-: 849: recvcounts, displs, recvtype, root,
-: 850: comm_ptr);
|
-: 851: /* --BEGIN ERROR HANDLING-- */
992: 852: if (mpi_errno)
-: 853: {
#####: 854: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 855: return mpi_errno;
-: 856: }
-: 857: /* --END ERROR HANDLING-- */
-: 858: /* gatherv to right group */
|
992: 859: root = 0;
992: 860: mpi_errno = MPIR_Gatherv(sendbuf, sendcount, sendtype, recvbuf,
-: 861: recvcounts, displs, recvtype, root,
-: 862: comm_ptr);
|
-: 863: /* --BEGIN ERROR HANDLING-- */
992: 864: if (mpi_errno)
-: 865: {
#####: 866: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 867: return mpi_errno;
-: 868: }
-: 869: /* --END ERROR HANDLING-- */
-: 870: }
-: 871: else {
-: 872: /* gatherv to left group */
|
1888: 873: root = 0;
1888: 874: mpi_errno = MPIR_Gatherv(sendbuf, sendcount, sendtype, recvbuf,
-: 875: recvcounts, displs, recvtype, root,
-: 876: comm_ptr);
|
-: 877: /* --BEGIN ERROR HANDLING-- */
1888: 878: if (mpi_errno)
-: 879: {
#####: 880: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 881: return mpi_errno;
-: 882: }
-: 883: /* --END ERROR HANDLING-- */
-: 884: /* gatherv from left group */
|
1888: 885: root = (rank == 0) ? MPI_ROOT : MPI_PROC_NULL;
1888: 886: mpi_errno = MPIR_Gatherv(sendbuf, sendcount, sendtype, recvbuf,
-: 887: recvcounts, displs, recvtype, root,
-: 888: comm_ptr);
|
-: 889: /* --BEGIN ERROR HANDLING-- */
1888: 890: if (mpi_errno)
-: 891: {
#####: 892: mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);
#####: 893: return mpi_errno;
-: 894: }
-: 895: /* --END ERROR HANDLING-- */
-: 896: }
-: 897:
-: 898: /* now do an intracommunicator broadcast within each group. we use
-: 899: a derived datatype to handle the displacements */
-: 900:
-: 901: /* Get the local intracommunicator */
|
2880: 902: if (!comm_ptr->local_comm)
90: 903: MPIR_Setup_intercomm_localcomm( comm_ptr );
-: 904:
2880: 905: newcomm_ptr = comm_ptr->local_comm;
-: 906:
2880: 907: NMPI_Type_indexed(remote_size, recvcounts, displs, recvtype,
-: 908: &newtype);
2880: 909: NMPI_Type_commit(&newtype);
-: 910:
2880: 911: mpi_errno = MPIR_Bcast(recvbuf, 1, newtype, 0, newcomm_ptr);
-: 912:
2880: 913: NMPI_Type_free(&newtype);
-: 914:
2880: 915: return mpi_errno;
-: 916:}
-: 917:/* end:nested */
-: 918:#endif
-: 919:
-: 920:#undef FUNCNAME
-: 921:#define FUNCNAME MPI_Allgatherv
-: 922:
-: 923:/*@
-: 924:
-: 925:MPI_Allgatherv - Gathers data from all tasks and deliver the combined data
-: 926: to all tasks
-: 927:
-: 928:Input Parameters:
-: 929:+ sendbuf - starting address of send buffer (choice)
-: 930:. sendcount - number of elements in send buffer (integer)
-: 931:. sendtype - data type of send buffer elements (handle)
-: 932:. recvcounts - integer array (of length group size)
-: 933:containing the number of elements that are to be received from each process
-: 934:. displs - integer array (of length group size). Entry
-: 935: 'i' specifies the displacement (relative to recvbuf ) at
-: 936:which to place the incoming data from process 'i'
-: 937:. recvtype - data type of receive buffer elements (handle)
-: 938:- comm - communicator (handle)
-: 939:
-: 940:Output Parameter:
-: 941:. recvbuf - address of receive buffer (choice)
-: 942:
-: 943:Notes:
-: 944: The MPI standard (1.0 and 1.1) says that
-: 945:.n
-: 946:.n
-: 947: The jth block of data sent from
-: 948: each proess is received by every process and placed in the jth block of the
-: 949: buffer 'recvbuf'.
-: 950:.n
-: 951:.n
-: 952: This is misleading; a better description is
-: 953:.n
-: 954:.n
-: 955: The block of data sent from the jth process is received by every
-: 956: process and placed in the jth block of the buffer 'recvbuf'.
-: 957:.n
-: 958:.n
-: 959: This text was suggested by Rajeev Thakur, and has been adopted as a
-: 960: clarification to the MPI standard by the MPI-Forum.
-: 961:
-: 962:.N ThreadSafe
-: 963:
-: 964:.N Fortran
-: 965:
-: 966:.N Errors
-: 967:.N MPI_ERR_BUFFER
-: 968:.N MPI_ERR_COUNT
-: 969:.N MPI_ERR_TYPE
-: 970:@*/
-: 971:int MPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
-: 972: void *recvbuf, int *recvcounts, int *displs,
-: 973: MPI_Datatype recvtype, MPI_Comm comm)
19814: 974:{
-: 975: static const char FCNAME[] = "MPI_Allgatherv";
19814: 976: int mpi_errno = MPI_SUCCESS;
19814: 977: MPID_Comm *comm_ptr = NULL;
19814: 978: MPIU_THREADPRIV_DECL;
-: 979: MPID_MPI_STATE_DECL(MPID_STATE_MPI_ALLGATHERV);
-: 980:
19814: 981: MPIR_ERRTEST_INITIALIZED_ORDIE();
-: 982:
19814: 983: MPIU_THREAD_CS_ENTER(ALLFUNC,);
-: 984: MPID_MPI_COLL_FUNC_ENTER(MPID_STATE_MPI_ALLGATHERV);
-: 985:
-: 986: /* Validate parameters, especially handles needing to be converted */
|
-: 987:# ifdef HAVE_ERROR_CHECKING
-: 988: {
-: 989: MPID_BEGIN_ERROR_CHECKS;
-: 990: {
19814: 991: MPIR_ERRTEST_COMM(comm, mpi_errno);
19814: 992: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 993: }
-: 994: MPID_END_ERROR_CHECKS;
-: 995: }
-: 996:# endif /* HAVE_ERROR_CHECKING */
-: 997:
-: 998: /* Convert MPI object handles to object pointers */
|
19812: 999: MPID_Comm_get_ptr( comm, comm_ptr );
-: 1000:
-: 1001: /* Validate parameters and objects (post conversion) */
|
-: 1002:# ifdef HAVE_ERROR_CHECKING
-: 1003: {
-: 1004: MPID_BEGIN_ERROR_CHECKS;
-: 1005: {
19812: 1006: MPID_Datatype *recvtype_ptr=NULL, *sendtype_ptr=NULL;
-: 1007: int i, comm_size;
-: 1008:
19812: 1009: MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
19812: 1010: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 1011:
19810: 1012: if (comm_ptr->comm_kind == MPID_INTERCOMM)
2880: 1013: MPIR_ERRTEST_SENDBUF_INPLACE(sendbuf, sendcount, mpi_errno);
19810: 1014: if (sendbuf != MPI_IN_PLACE) {
18900: 1015: MPIR_ERRTEST_COUNT(sendcount, mpi_errno);
18900: 1016: MPIR_ERRTEST_DATATYPE(sendtype, "sendtype", mpi_errno);
18900: 1017: if (HANDLE_GET_KIND(sendtype) != HANDLE_KIND_BUILTIN) {
362: 1018: MPID_Datatype_get_ptr(sendtype, sendtype_ptr);
362: 1019: MPID_Datatype_valid_ptr( sendtype_ptr, mpi_errno );
362: 1020: MPID_Datatype_committed_ptr( sendtype_ptr, mpi_errno );
-: 1021: }
18900: 1022: MPIR_ERRTEST_USERBUFFER(sendbuf,sendcount,sendtype,mpi_errno);
-: 1023: }
-: 1024:
19810: 1025: if (comm_ptr->comm_kind == MPID_INTRACOMM)
16930: 1026: comm_size = comm_ptr->local_size;
-: 1027: else
2880: 1028: comm_size = comm_ptr->remote_size;
-: 1029:
93540: 1030: for (i=0; i<comm_size; i++) {
73730: 1031: MPIR_ERRTEST_COUNT(recvcounts[i], mpi_errno);
73730: 1032: MPIR_ERRTEST_DATATYPE(recvtype, "recvtype", mpi_errno);
-: 1033: }
-: 1034:
19810: 1035: if (HANDLE_GET_KIND(recvtype) != HANDLE_KIND_BUILTIN) {
360: 1036: MPID_Datatype_get_ptr(recvtype, recvtype_ptr);
360: 1037: MPID_Datatype_valid_ptr( recvtype_ptr, mpi_errno );
360: 1038: MPID_Datatype_committed_ptr( recvtype_ptr, mpi_errno );
-: 1039: }
22238: 1040: for (i=0; i<comm_size; i++) {
21100: 1041: if (recvcounts[i] > 0) {
18672: 1042: MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf,recvcounts[i],mpi_errno);
18672: 1043: MPIR_ERRTEST_USERBUFFER(recvbuf,recvcounts[i],recvtype,mpi_errno);
-: 1044: break;
-: 1045: }
-: 1046: }
-: 1047:
19810: 1048: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 1049: }
-: 1050: MPID_END_ERROR_CHECKS;
-: 1051: }
-: 1052:# endif /* HAVE_ERROR_CHECKING */
-: 1053:
-: 1054: /* ... body of routine ... */
-: 1055:
|
19806: 1056: if (comm_ptr->coll_fns != NULL && comm_ptr->coll_fns->Allgatherv != NULL)
-: 1057: {
|
#####: 1058: mpi_errno = comm_ptr->coll_fns->Allgatherv(sendbuf, sendcount,
-: 1059: sendtype, recvbuf,
-: 1060: recvcounts, displs,
-: 1061: recvtype, comm_ptr);
-: 1062: }
-: 1063: else
-: 1064: {
|
19806: 1065: MPIU_THREADPRIV_GET;
-: 1066:
19806: 1067: MPIR_Nest_incr();
19806: 1068: if (comm_ptr->comm_kind == MPID_INTRACOMM)
-: 1069: /* intracommunicator */
16926: 1070: mpi_errno = MPIR_Allgatherv(sendbuf, sendcount,
-: 1071: sendtype, recvbuf,
-: 1072: recvcounts, displs,
-: 1073: recvtype, comm_ptr);
-: 1074: else {
-: 1075: /* intracommunicator */
2880: 1076: mpi_errno = MPIR_Allgatherv_inter(sendbuf, sendcount,
-: 1077: sendtype, recvbuf,
-: 1078: recvcounts, displs,
-: 1079: recvtype, comm_ptr);
-: 1080: }
19806: 1081: MPIR_Nest_decr();
-: 1082: }
-: 1083:
|
19806: 1084: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 1085:
-: 1086: /* ... end of body of routine ... */
-: 1087:
|
19814: 1088: fn_exit:
|
-: 1089: MPID_MPI_COLL_FUNC_EXIT(MPID_STATE_MPI_ALLGATHERV);
|
19814: 1090: MPIU_THREAD_CS_EXIT(ALLFUNC,);
19814: 1091: return mpi_errno;
-: 1092:
|
8: 1093: fn_fail:
-: 1094: /* --BEGIN ERROR HANDLING-- */
-: 1095:# ifdef HAVE_ERROR_CHECKING
-: 1096: {
8: 1097: mpi_errno = MPIR_Err_create_code(
-: 1098: mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_allgatherv",
-: 1099: "**mpi_allgatherv %p %d %D %p %p %p %D %C", sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm);
-: 1100: }
-: 1101:# endif
8: 1102: mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
8: 1103: goto fn_exit;
-: 1104: /* --END ERROR HANDLING-- */
-: 1105:}
|