|
例子
#include "mpi.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main( argc, argv )
int argc;
char *argv[];
{
int rank, size;
int chunk = 2;
/*发送到一个进程的数据块的大小*/
int i,j;
int *sb;
int *rb;
int status, gstatus;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
sb = (int *)malloc(size*chunk*sizeof(int));/*申请发送缓冲区*/
if ( !sb ) {
perror( "can't allocate send buffer" );
MPI_Abort(MPI_COMM_WORLD,EXIT_FAILURE);
}
rb = (int *)malloc(size*chunk*sizeof(int));/*申请接收缓冲区*/
if ( !rb ) {
perror( "can't allocate recv buffer");
free(sb);
MPI_Abort(MPI_COMM_WORLD,EXIT_FAILURE);
}
for ( i=0 ; i < size ; i++ ) {
for ( j=0 ; j < chunk ; j++ ) {
sb[i*chunk+j] = rank + i*chunk+j;/*设置发送缓冲区的数据*/
printf("myid=%d,send to id=%d, data[%d]=%d\n",rank,i,j,sb[i*chunk+j]);
rb[i*chunk+j] = 0;/*将接收缓冲区清0*/
}
}
/* 执行MPI_Alltoall 调用*/
MPI_Alltoall(sb,chunk,MPI_INT,rb,chunk,MPI_INT,
MPI_COMM_WORLD);
for ( i=0 ; i < size ; i++ ) {
for ( j=0 ; j < chunk ; j++ ) {
printf("myid=%d,recv from id=%d, data[%d]=%d\n",rank,i,j,rb[i*chunk+j]);
/*打印接收缓冲区从其它进程接收的数据*/
}
}
free(sb);
free(rb);
MPI_Finalize();
}
MPI_ALLTOALLV(sendbuf, sendcounts, sdispls, sendtype,
recvbuf,
recvcounts, rdispls, recvtype, comm)
INsendbuf发送消息缓冲区的起始地址(可选数据类型)
INsendcounts 向每个进程发送的数据个数(整型数组)
INsdispls向每个进程发送数据的位移(整型数组)
INsendtype 发送数据的数据类型(句柄)
OUT recvbuf接收消息缓冲区的起始地址(可选数据类型)
INrecvcounts 从每个进程中接收的数据个数(整型数组)
INrdispls从每个进程接收的数据在接收缓冲区的位移(整型数组)
INrecvtype 接收数据的数据类型(句柄)
INcomm 通信域(句柄)
int MPI_Alltoallv(void* sendbuf, int *sendcounts, int *sdispls,
MPI_Datatype sendtype, void* recvbuf,
int *recvcounts, int *rdispls,
MPI_Datatype recvtype, MPI_Comm comm)
MPI_ALLTOALLV(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPE, RECVBUF,
RECVCOUNTS, RDISPLS, RECVTYPE, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SDISPLS(*), SENDTYPE, RECVCOUNTS(*),
RDISPLS(*), RECVTYPE, COMM, IERROR
正如MPI_ALLGATHERV和MPI_ALLGATHER的关系一样,MPI_ALLTOALLV在MPI_ALLTOALL的基础上进一步增加了灵活性,它可以由sdispls指定待发送数据的位置,在接收方则由rdispls指定接收的数据存放在缓冲区的偏移量。
所有参数对每个进程都是有意义的,并且所有进程中的comm值必须一致。
MPI_ALLTOALL和MPI_ALLTOALLV可以实现n次独立的点对点通信,但也有限制:1)所有数据必须是同一类型;2)所有的消息必须按顺序进行散发和收集。
|
|