2016-05-13 1157 views
0

我想修改我的程序,使代码看起来更好。现在我正在使用MPI_Send和MPI_Recv,但我试图使它与MPI_Scatter一起工作。我有一个名为All_vals的数组,我试图将Sub_arr_len等份发送给每个从站。 所以在我第一次找到我应该发送给每个从机的值的数量之后,我必须发送并接收值的数量,然后发送并接收这些值。我试图将那些send/recv改为MPI_Scatter,并考虑一下这种情况:值不会被分成相等的部分,比如我有20个数字,但是我有3个进程。所以奴隶应该有20/3 = 6的值,但主人应该有其余的20-2 * 6 = 8。
这里是我想要编辑的部分:MPI_Scatter用法

int master(int argc, char **argv){ 
... 
for (i=0; i<ntasks; i++) 
    { 
    Sub_arr_len[i]=Num_vals/ntasks;  //Finding the number of values I should send to every process    
    printf("\n\nIn range %d there are %d\n\n",i,Sub_arr_len[i]); 
    } 

    for(i=1;i<ntasks;i++) { 
     Sub_len = Sub_arr_len[i]; 
     MPI_Isend(&Sub_len,1, MPI_INTEGER, i, i, MPI_COMM_WORLD, &request); 
     MPI_Wait(&request, &status); 
     Sub_arr_start += Sub_arr_len[i-1]; 
     printf("\r\nSub_arr_start = %d ",Sub_arr_start); 
     MPI_Isend(&All_vals[Sub_arr_start],Sub_len, MPI_INTEGER, i, i, MPI_COMM_WORLD, &request); 
     MPI_Wait(&request, &status); 
    } 
... 
} 


int slave(){ 
MPI_Irecv(&Sub_arr_len, 1, MPI_INTEGER, 0, myrank, MPI_COMM_WORLD, &request); 
    MPI_Wait(&request,&status); 
    printf("\r\nSLAVE:Sub_arr_len = %d\n\n",Sub_arr_len); 
    All_vals = (int*) malloc(Sub_arr_len * sizeof(MPI_INTEGER)); 

    MPI_Irecv(&All_vals[0], Sub_arr_len, MPI_INTEGER, 0, myrank, MPI_COMM_WORLD, &request); 
    MPI_Wait(&request,&status); 
} 

我试图使分散的事,但我做错了什么,所以如果有人帮助我建立它,我喜欢。

回答

0

对于MPI_Scatter,涉及的每个等级必须接收相同数量的元素,包括根。通常,根进程是分散操作中的普通参与者,并“接收”他自己的块。这意味着您还需要为根进程指定接收缓冲区。你基本上有以下几种选择:

  1. 使用MPI_IN_PLACErecvbuf根,做根不会送什么东西给自己。将它与从根分散原始sendbuffer的尾部,使得这个“尾部”具有可被进程数量整除的许多元素。例如。为20个元素分散&All_vals[2]其中共有18个元素,每个元素6个(包括再次)。然后根可以使用All_vals [0-7]。
  2. 用几个不做任何事情的元素填充sendbuffer,这样可以被进程数量整除。
  3. 使用MPI_Scatterv向每个等级发送不等数量的元素。 Here is a good example如何正确设置发送计数和位移

最后一个选项有一些明显的优点。它在进程间创建最小负载不平衡,并允许所有进程使用相同的代码。如果适用,第二个选项非常简单,并且仍然具有良好的负载平衡。