您的位置:首页 > 其它

并行群集通信:全互换 Alltoall

2015-01-23 10:37 246 查看
函数原型:

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 的例子:

/*
* =====================================================================================
*
*       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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: