⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 allgatherv.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 3 页
字号:
            }            MPIU_Free((char *)tmp_buf+recvtype_true_lb);         }        #ifdef MPID_HAS_HETERO        else {            /* heterogeneous. need to use temp. buffer. */            NMPI_Pack_size(total_count, recvtype, comm, &tmp_buf_size);            tmp_buf = MPIU_Malloc(tmp_buf_size);	    /* --BEGIN ERROR HANDLING-- */            if (!tmp_buf)	    {                mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);                return mpi_errno;            }	    /* --END ERROR HANDLING-- */                        /* calculate the value of nbytes, the number of bytes in packed               representation corresponding to a single recvtype. Since               MPI_Pack_size returns only an upper bound on                the size, to get the real size we actually pack some data               into tmp_buf and see by how much 'position' is incremented. */                        position = 0;            NMPI_Pack(recvbuf, 1, recvtype, tmp_buf, tmp_buf_size,                      &position, comm);            nbytes = position;                        /* pack local data into right location in tmp_buf */            position = 0;            for (i=0; i<rank; i++) position += recvcounts[i];            position *= nbytes;                        if (sendbuf != MPI_IN_PLACE) {                NMPI_Pack(sendbuf, sendcount, sendtype, tmp_buf,                          tmp_buf_size, &position, comm);            }            else {                /* if in_place specified, local data is found in recvbuf */                 NMPI_Pack(((char *)recvbuf + displs[rank]*recvtype_extent),                           recvcounts[rank], recvtype, tmp_buf,                          tmp_buf_size, &position, comm);            }                        curr_cnt = recvcounts[rank]*nbytes;                        mask = 0x1;            i = 0;            while (mask < comm_size) {                dst = rank ^ mask;                                /* find offset into send and recv buffers. zero out                    the least significant "i" bits of rank and dst to                    find root of src and dst subtrees. Use ranks of                    roots as index to send from and recv into buffer. */                                 dst_tree_root = dst >> i;                dst_tree_root <<= i;                                my_tree_root = rank >> i;                my_tree_root <<= i;                                send_offset = 0;                for (j=0; j<my_tree_root; j++)                    send_offset += recvcounts[j];                send_offset *= nbytes;                                recv_offset = 0;                for (j=0; j<dst_tree_root; j++)                    recv_offset += recvcounts[j];                recv_offset *= nbytes;                                if (dst < comm_size) {                    mpi_errno = MPIC_Sendrecv(((char *)tmp_buf + send_offset),                                              curr_cnt, MPI_BYTE, dst,                                              MPIR_ALLGATHERV_TAG,                                                ((char *)tmp_buf + recv_offset),                                              tmp_buf_size-recv_offset, MPI_BYTE, dst,                                              MPIR_ALLGATHERV_TAG, comm, &status);                    /* for convenience, recv is posted for a bigger amount                       than will be sent */ 		    /* --BEGIN ERROR HANDLING-- */                    if (mpi_errno)		    {			mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);			return mpi_errno;		    }		    /* --END ERROR HANDLING-- */                                        NMPI_Get_count(&status, MPI_BYTE, &last_recv_cnt);                    curr_cnt += last_recv_cnt;                }                                /* if some processes in this process's subtree in this step                   did not have any destination process to communicate with                   because of non-power-of-two, we need to send them the                   data that they would normally have received from those                   processes. That is, the haves in this subtree must send to                   the havenots. We use a logarithmic recursive-halfing algorithm                   for this. */                                if (dst_tree_root + mask > comm_size) {                    nprocs_completed = comm_size - my_tree_root - mask;                    /* nprocs_completed is the number of processes in this                       subtree that have all the data. Send data to others                       in a tree fashion. First find root of current tree                       that is being divided into two. k is the number of                       least-significant bits in this process's rank that                       must be zeroed out to find the rank of the root */                     j = mask;                    k = 0;                    while (j) {                        j >>= 1;                        k++;                    }                    k--;                                        offset = 0;                    for (j=0; j<(my_tree_root+mask); j++)                        offset += recvcounts[j];                    offset *= nbytes;                    tmp_mask = mask >> 1;                                        while (tmp_mask) {                        dst = rank ^ tmp_mask;                                                tree_root = rank >> k;                        tree_root <<= k;                                                /* send only if this proc has data and destination                           doesn't have data. at any step, multiple processes                           can send if they have the data */                        if ((dst > rank) &&                             (rank < tree_root + nprocs_completed)                            && (dst >= tree_root + nprocs_completed)) {                                                        mpi_errno = MPIC_Send(((char *)tmp_buf + offset),                                                  last_recv_cnt, MPI_BYTE,                                                  dst, MPIR_ALLGATHERV_TAG,                                                  comm);                              /* last_recv_cnt was set in the previous                               receive. that's the amount of data to be                               sent now. */			    /* --BEGIN ERROR HANDLING-- */                            if (mpi_errno)			    {				mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);				return mpi_errno;			    }			    /* --END ERROR HANDLING-- */                        }                        /* recv only if this proc. doesn't have data and sender                           has data */                        else if ((dst < rank) &&                                  (dst < tree_root + nprocs_completed) &&                                 (rank >= tree_root + nprocs_completed)) {                            mpi_errno = MPIC_Recv(((char *)tmp_buf + offset),                                                  tmp_buf_size-offset, MPI_BYTE,                                                  dst,                                                  MPIR_ALLGATHERV_TAG,                                                  comm, &status);                             /* for convenience, recv is posted for a bigger amount                               than will be sent */ 			    /* --BEGIN ERROR HANDLING-- */                            if (mpi_errno)			    {				mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);				return mpi_errno;			    }			    /* --END ERROR HANDLING-- */                            NMPI_Get_count(&status, MPI_BYTE, &last_recv_cnt);                            curr_cnt += last_recv_cnt;                        }                        tmp_mask >>= 1;                        k--;                    }                }                mask <<= 1;                i++;            }                    position = 0;            for (j=0; j<comm_size; j++) {                if ((sendbuf != MPI_IN_PLACE) || (j != rank)) {                    /* not necessary to unpack if in_place and                       j==rank. otherwise unpack. */                    NMPI_Unpack(tmp_buf, tmp_buf_size, &position,                                 ((char *)recvbuf + displs[j]*recvtype_extent),                                recvcounts[j], recvtype, comm);                }            }                        MPIU_Free(tmp_buf);        }#endif /* MPID_HAS_HETERO */    }    else if (total_count*recvtype_size < MPIR_ALLGATHER_SHORT_MSG) {        /* Short message and non-power-of-two no. of processes. Use         * Bruck algorithm (see description above). */         /* allocate a temporary buffer of the same size as recvbuf. */        /* get true extent of recvtype */        mpi_errno = NMPI_Type_get_true_extent(recvtype,                                               &recvtype_true_lb,                                              &recvtype_true_extent);        /* --BEGIN ERROR HANDLING-- */        if (mpi_errno)	{	    mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);	    return mpi_errno;	}        /* --END ERROR HANDLING-- */                    recvbuf_extent = total_count *            (MPIR_MAX(recvtype_true_extent, recvtype_extent));        tmp_buf = MPIU_Malloc(recvbuf_extent);        /* --BEGIN ERROR HANDLING-- */        if (!tmp_buf) {            mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0 );            return mpi_errno;        }	/* --END ERROR HANDLING-- */                    /* adjust for potential negative lower bound in datatype */        tmp_buf = (void *)((char*)tmp_buf - recvtype_true_lb);        /* copy local data to the top of tmp_buf */         if (sendbuf != MPI_IN_PLACE) {            mpi_errno = MPIR_Localcopy (sendbuf, sendcount, sendtype,                                        tmp_buf, recvcounts[rank], recvtype);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */        }        else {            mpi_errno = MPIR_Localcopy(((char *)recvbuf +                                        displs[rank]*recvtype_extent),                                        recvcounts[rank], recvtype,                                       tmp_buf, recvcounts[rank], recvtype);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */        }                /* do the first \floor(\lg p) steps */        curr_cnt = recvcounts[rank];        pof2 = 1;        while (pof2 <= comm_size/2) {            src = (rank + pof2) % comm_size;            dst = (rank - pof2 + comm_size) % comm_size;                        mpi_errno = MPIC_Sendrecv(tmp_buf, curr_cnt, recvtype, dst,                                      MPIR_ALLGATHERV_TAG,                                  ((char *)tmp_buf + curr_cnt*recvtype_extent),                                      total_count - curr_cnt, recvtype,                                      src, MPIR_ALLGATHERV_TAG, comm, &status);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */            NMPI_Get_count(&status, recvtype, &recv_cnt);            curr_cnt += recv_cnt;            pof2 *= 2;        }        /* if comm_size is not a power of two, one more step is needed */        rem = comm_size - pof2;        if (rem) {            src = (rank + pof2) % comm_size;            dst = (rank - pof2 + comm_size) % comm_size;            send_cnt = 0;            for (i=0; i<rem; i++)                send_cnt += recvcounts[(rank+i)%comm_size];            mpi_errno = MPIC_Sendrecv(tmp_buf, send_cnt, recvtype,                                      dst, MPIR_ALLGATHERV_TAG,                                  ((char *)tmp_buf + curr_cnt*recvtype_extent),                                      total_count - curr_cnt, recvtype,                                      src, MPIR_ALLGATHERV_TAG, comm,                                      MPI_STATUS_IGNORE);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */        }        /* Rotate blocks in tmp_buf down by (rank) blocks and store         * result in recvbuf. */        send_cnt = 0;        for (i=0; i < (comm_size-rank); i++) {            j = (rank+i)%comm_size;            mpi_errno = MPIR_Localcopy((char *)tmp_buf + send_cnt*recvtype_extent,                                        recvcounts[j], recvtype,                                   (char *)recvbuf + displs[j]*recvtype_extent,                                        recvcounts[j], recvtype);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */            send_cnt += recvcounts[j];        }        for (i=0; i<rank; i++) {            mpi_errno = MPIR_Localcopy((char *)tmp_buf + send_cnt*recvtype_extent,                                        recvcounts[i], recvtype,                                   (char *)recvbuf + displs[i]*recvtype_extent,                                        recvcounts[i], recvtype);	    /* --BEGIN ERROR HANDLING-- */            if (mpi_errno)	    {		mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0);		return mpi_errno;	    }	    /* --END ERROR HANDLING-- */            send_cnt += recvcounts[i];        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -