/** Broadcast on a group. Collective. * * @param[in] scope ARMCI scope * @param[inout] buf Input on the root, output on all other processes * @param[in] len Number of bytes in the message * @param[in] abs_root Absolute rank of the process at the root of the broadcast * @param[in] group ARMCI group on which to perform communication */ void armci_msg_group_bcast_scope(int scope, void *buf_in, int len, int abs_root, ARMCI_Group *group) { int grp_root; void **buf; if (scope == SCOPE_ALL || scope == SCOPE_MASTERS) { /* Is the buffer an input or an output? */ if (ARMCI_GROUP_WORLD.rank == abs_root) ARMCII_Buf_prepare_read_vec(&buf_in, &buf, 1, len); else ARMCII_Buf_prepare_write_vec(&buf_in, &buf, 1, len); grp_root = ARMCII_Translate_absolute_to_group(group, abs_root); ARMCII_Assert(grp_root >= 0 && grp_root < group->size); MPI_Bcast(buf[0], len, MPI_BYTE, grp_root, group->comm); if (ARMCI_GROUP_WORLD.rank == abs_root) ARMCII_Buf_finish_read_vec(&buf_in, buf, 1, len); else ARMCII_Buf_finish_write_vec(&buf_in, buf, 1, len); } else /* SCOPE_NODE */ { grp_root = 0; /* This is a self-broadcast, which is a no-op. */ } }
/** Receive a two-sided message. * * @param[in] tag Message tag (must match on sender and receiver) * @param[in] buf Buffer containing the message * @param[in] nbytes_buf Size of the buffer in bytes * @param[out] nbytes_msg Length of the message received in bytes (NULL to ignore) * @param[in] src Source process id */ void armci_msg_rcv(int tag, void *buf_out, int nbytes_buf, int *nbytes_msg, int src) { void **buf; MPI_Status status; ARMCII_Buf_prepare_write_vec(&buf_out, &buf, 1, nbytes_buf); MPI_Recv(buf[0], nbytes_buf, MPI_BYTE, src, tag, ARMCI_GROUP_WORLD.comm, &status); ARMCII_Buf_finish_write_vec(&buf_out, buf, 1, nbytes_buf); if (nbytes_msg != NULL) MPI_Get_count(&status, MPI_BYTE, nbytes_msg); }
/** Receive a two-sided message from any source. * * @param[in] tag Message tag (must match on sender and receiver) * @param[in] buf Buffer containing the message * @param[in] nbytes_buf Size of the buffer in bytes * @param[out] nbytes_msg Length of the message received in bytes (NULL to ignore) * @return Rank of the message source */ int armci_msg_rcvany(int tag, void *buf_out, int nbytes_buf, int *nbytes_msg) { void **buf; MPI_Status status; ARMCII_Buf_prepare_write_vec(&buf_out, &buf, 1, nbytes_buf); MPI_Recv(buf[0], nbytes_buf, MPI_BYTE, MPI_ANY_SOURCE, tag, ARMCI_GROUP_WORLD.comm, &status); ARMCII_Buf_finish_write_vec(&buf_out, buf, 1, nbytes_buf); if (nbytes_msg != NULL) MPI_Get_count(&status, MPI_BYTE, nbytes_msg); return status.MPI_SOURCE; }
/** Broadcast a message. Collective. * * @param[in] buffer Source buffer on root, destination elsewhere. * @param[in] len Length of the message in bytes. * @param[in] root Rank of the root process. */ void armci_msg_bcast(void *buf_in, int len, int root) { void **buf; /* Is the buffer an input or an output? */ if (ARMCI_GROUP_WORLD.rank == root) ARMCII_Buf_prepare_read_vec(&buf_in, &buf, 1, len); else ARMCII_Buf_prepare_write_vec(&buf_in, &buf, 1, len); MPI_Bcast(buf[0], len, MPI_BYTE, root, ARMCI_GROUP_WORLD.comm); if (ARMCI_GROUP_WORLD.rank == root) ARMCII_Buf_finish_read_vec(&buf_in, buf, 1, len); else ARMCII_Buf_finish_write_vec(&buf_in, buf, 1, len); }
/** Generalized I/O vector one-sided get. * * @param[in] iov Vector of transfer information. * @param[in] iov_len Length of iov. * @param[in] proc Target process. * @return Success 0, otherwise non-zero. */ int PARMCI_GetV(armci_giov_t *iov, int iov_len, int proc) { int v; for (v = 0; v < iov_len; v++) { void **dst_buf; int overlapping, same_alloc; if (iov[v].ptr_array_len == 0) continue; // NOP // if (iov[v].bytes == 0) continue; // NOP // // overlapping = ARMCII_Iov_check_overlap(iov[v].src_ptr_array, iov[v].ptr_array_len, iov[v].bytes); overlapping = ARMCII_Iov_check_overlap(iov[v].dst_ptr_array, iov[v].ptr_array_len, iov[v].bytes); same_alloc = ARMCII_Iov_check_same_allocation(iov[v].src_ptr_array, iov[v].ptr_array_len, proc); ARMCII_Buf_prepare_write_vec(iov[v].dst_ptr_array, &dst_buf, iov[v].ptr_array_len, iov[v].bytes); ARMCII_Iov_op_dispatch(ARMCII_OP_GET, iov[v].src_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes, 0, overlapping, same_alloc, proc); ARMCII_Buf_finish_write_vec(iov[v].dst_ptr_array, dst_buf, iov[v].ptr_array_len, iov[v].bytes); } return 0; }