并行群集通信:全互换 Alltoall

来源:互联网 发布:淘宝商城婴儿玩具店 编辑:程序博客网 时间:2024/05/01 20:17
函数原型:
MPI_ALLTOALL(sendbuf, sendcount, sendtype, recvbuf, recvcount,
recvtype, comm)
IN sendbuf 发送消息缓冲区的起始地址(可选数据类型)
IN sendcount 发送到每个进程的数据个数(整型)
IN sendtype 发送消息缓冲区中的数据类型(句柄)
OUT recvbuf 接收消息缓冲区的起始地址(可选数据类型)
IN recvcount 从每个进程中接收的元素个数(整型)
IN recvtype 接收消息缓冲区的数据类型(句柄)
IN comm 通信域(句柄)
int MPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype,
MPI_Comm comm)
MPI_ALLTOALL(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
RECVTYPE, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, COMM, 
IERROR

  MPI_ALLTOALL是组内进程之间完全的消息交换,其中每一个进程都向其它所有的进程发送消息,同时,每一个进程都从其它所有的进程接收消息。
MPI_ALLGATHER每个进程散发一个相同的消息给所有的进程,MPI_ALLTOALL散发给不同进程的消息是不同的,因此它的发送缓冲区也 是一个数组。MPI_ALLTOALL的每个进程可以向每个接收者发送数目不同的数据。第i个进程发送的第j块数据将被第j个进程接收并存放在其接收消息 缓冲区recvbuf的第i块。每个进程的sendcount和sendtype的类型必须和所有其他进程的recvcount和recvtype相同, 这就意谓着在每个进程和根进程之间,发送的数据量必须和接收的数据量相等。
调用MPI_ALLTOALL相当于每个进程依次将它的发送缓冲区的第i块数据发送给第i个进程。同时每个进程又都依次从第j个进程接收数据放到各自接收缓冲区的第j块数据区的位置。


Alltoall 的示意图:

全互换 Alltoall 的例子 - 老莫 - motioo 的博客


Alltoall 的例子:
/** =====================================================================================**       Filename: alltoall.cpp**    Description: MPI_Alltoall 函数**        Version: 1.0*        Created: 2007年11月13日 23时07分12秒 CST*       Revision: none*       Compiler: mpicxx -DMPICH_IGNORE_CXX_SEEK -o alltoall.exe alltoall.cpp**         Author:   Tiao Lu, tlu@math.pku.edu.cn*        Company: School of Mathematical Sciences, Peking University*         edit:   DH,USTC ,2105,1,23.* =====================================================================================*/#include <iostream>#include "mpi.h"using namespace std;int main(int argc, char * argv[]){    int rank, size;    MPI_Init(&argc,&argv);    MPI_Comm_size(MPI_COMM_WORLD, &size);    MPI_Comm_rank(MPI_COMM_WORLD, &rank);    //任意一个CPU 向别的CPU发送的数据长度都一样。    //这个例子中,我们使用的数据长度是1.    //你可以改成2 看看有什么不同。    int sendcount = 1;    //recvcount 和 sendcount 必须相等    int recvcount = sendcount;    //发送缓冲区和接收缓冲区的数据长度    int len = sendcount*size;    int *sendbuf = new int[len];    int *recvbuf = new int[len];    //给发送缓冲区赋值    for(int i =0; i< len ; i ++) sendbuf[i] = i+size*rank;    MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT, MPI_COMM_WORLD);//输出发送缓冲区的值    for(int i=0;i<size;i++){        if(i==rank){            cout<<"Sendbuf on process "<<rank<<" holds " <<len<<                " data :"<<endl;            for(int j=0;j<len;j++)                cout<<sendbuf[j]<<" ";            cout<<endl;        }        MPI_Barrier(MPI_COMM_WORLD);    }        if(rank==0) cout<<endl;    MPI_Barrier(MPI_COMM_WORLD);    //输出接收缓冲区的值    for(int i=0;i<size;i++){        if(i==rank){            cout<<"Recvbuf on process "<<rank<<" holds " <<len<<                " data :"<<endl;            for(int j=0;j<len;j++)                cout<<recvbuf[j]<<" ";            cout<<endl;        }        MPI_Barrier(MPI_COMM_WORLD);    }    delete [] sendbuf;    delete [] recvbuf;    MPI_Finalize();   // return EXIT_SUCCESS;    return 0;}


/**计算结果
tlu:lecture$ mpirun -np 3 ./alltoall.exe 
Sendbuf on process 0 holds 3 data :
0 1 2 
Sendbuf on process 1 holds 3 data :
3 4 5 
Sendbuf on process 2 holds 3 data :
6 7 8 

Recvbuf on process 0 holds 3 data :
0 3 6 
Recvbuf on process 1 holds 3 data :
1 4 7 
Recvbuf on process 2 holds 3 data :
2 5 8 

*/

原文链接:http://motioo.blog.163.com/blog/static/117718291200954102827725/

0 0
原创粉丝点击