为数据数组创建MPI派生数据类型

时间:2014-08-05 16:24:00

标签: parallel-processing mpi

在每个处理器上,我都有一个一维的阵列,其中的每一部分都会被发送到不同的处理器 假设它具有以下形状:

加倍[n];

如果n = 1200

the size of array is 1200*sizeof(d)   

e.g。我在4个处理器上运行
前50个元素将保留在拥有它们的同一个处理器上,

first 50 stays on rank  
next 100 goes to mod(rank+1,nproc)  
next 70  goes to mod(rank+2,nproc)  
next 80  goes to mod(rank+3,nproc)  

next 50*2  stays on rank  
next 100*2 goes  to mod(rank+1,nproc)  
next 70*2  goes  to mod(rank+2,nproc)  
next 80*2  goes  to mod(rank+3,nproc)  

next 50 stays on rank  
next 100 goes to mod(rank+1,nproc)  
next 70  goes to mod(rank+2,nproc)   
next 80  goes to mod(rank+3,nproc)  

在下一步中,数字可能不同2000

first 150 stays on rank  
next 100 goes to mod(rank+1,nproc)  
next 100  goes to mod(rank+2,nproc)  
next 150  goes to mod(rank+3,nproc)  

next 150*2  stays on rank  
next 100*2 goes  to mod(rank+1,nproc)  
next 100*2  goes  to mod(rank+2,nproc)  
next 150*2  goes  to mod(rank+3,nproc)  

next 150 stays on rank  
next 100 goes to mod(rank+1,nproc)  
next 100  goes to mod(rank+2,nproc)  
next 150  goes to mod(rank+3,nproc)  

等等,

发送这些数据的最佳方式是什么!如果我使用阻塞发送recv(这是我目前正在使用的方式),我将创建临时数组复制所有需要进入排名+ 1然后发送的数据。

有没有办法创建一个派生数据类型,我可以将newtype发送到排名。

在第一步上进行mod(rank + 1,nproc)的数据类型

[50 offset][100 d][200 offset][200d][350 offset][100d]

next 100 goes to mod(rank+1,nproc)  
... 
next 100*2 goes  to mod(rank+1,nproc)  
...  
next 100 goes to mod(rank+1,nproc)   

并在下一步

[150 offset][100 d][450 offset][200d][650 offset][100d]

是否有任何建议如何创建派生数据类型?

我不能为每个等级创建不同的数据类型(一个用于排名+ 1,另一个用于排名+ 2,....),如果我有1024个或更多处理器,我必须创建1024个数据类型at每次迭代并在最后销毁它们(根据我之前使用Indexed数据类型创建许多数据类型的经验,或者在每次迭代时释放它们并且在任何人都知道更多关于它的情况下都很昂贵吗?)

1 个答案:

答案 0 :(得分:0)

你写道:

  

如果我使用阻止发送recv(这是我目前的方式   使用)我会创建临时数组复制所需的所有数据   去排名+ 1然后发送。

您不一定需要这样做:您只需在单独的消息中发送每个块。如果考虑性能,您可以以非阻塞方式发送它们,并且只在最后一个发送后才阻止。

也就是说,如果您只想为每个进程发送一条消息,那么Indexed数据类型就是您所需要的。在发布时,this site有一个很好的解释,但这是短版本:

对于您的示例中的情况:

[50 offset][100 d][200 offset][200d][350 offset][100d]

你要定义一个数据类型(警告,未经测试的代码):

double a[1000];
MPI_Datatype newType;
int numBlocks = 3;       // 3 blocks of data
int displacements[3];    // at what position does each block start
int blockLengths[3];     // how many elements does each block contain
displacements[0] = 50;   // 50 offset
blockLengths[0] = 100;   // 100 d
displacements[1] = 200;  // 200 offset
blockLengths[1] = 200;   // 200 d
displacements[2] = 350;  // 350 offset
blockLengths[2] = 100;   // 100 d

MPI_Type_Indexed(3, blockLengths, displacements, MPI_DOUBLE, &newType);
MPI_Type_commit(&newType);
MPI_Send(a, 1, newType, ...);

请注意,需要在接收端定义类似的数据类型:接收进程只需将此消息作为MPI_DOUBLE的数组接收,前提是其接收缓冲区为足够大。

另请注意,由于每个排名和每个迭代步骤的数据类型布局都不同,因此每次必须定义提交类似的数据类型。您还应该使用MPI_Type_free()释放旧类型。