2016-01-23 77 views
1

我想通過使用無阻塞版本的通信在同一個通信器上分散從0到所有其他的兩個不同的獨立數組。連續調用MPI_IScatterv與相同的通信器

東西沿着這些路線:

//do some stuff with arrays here... 
MPI_IScatterv(array1, partial_size1, displs1, 
      MPI_DOUBLE, local1, partial_size1, 
      MPI_DOUBLE, 0, some_communicator, &request); 
MPI_IScatterv(array2, partial_size2, displs2, 
      MPI_DOUBLE, local2, partial_size2, 
      MPI_DOUBLE, 0, some_communicator, &request); 
//do some stuff where none of the arrays is needed... 
MPI_Wait(&request, &status); 
//do stuff with the arrays... 

所以......有沒有可能(或者更確切地說,如果它是保證始終準確無誤)使用相同的通信使用兩個連續調用MPI_IScatterv,或可能會影響結果 - 由於沒有標籤而弄亂了這兩個消息的消息?

回答

0

是的,可以根據MPI standard一次執行多個非阻塞集體操作。特別是在第197頁的5.12節中。非阻塞共同操作:

多個非阻塞共同操作可以在優秀的單一傳播者。如果非阻塞調用導致某些系統資源耗盡,那麼它將失敗並生成MPI異常。 MPI的質量實施應確保 僅在病理情況下才會發生。 也就是說,一個MPI實現應該能夠支持大量未決的非阻塞操作,即 。

儘管如此,確保不同request被用於連續調用MPI_Iscatterv()。函數MPI_Waitall()對於檢查多個非阻塞操作的完成很有用。

MPI_Request requests[2]; 
MPI_Iscatterv(...,&requests[0]); 
MPI_Iscatterv(...,&requests[1]); 
MPI_Waitall(2,requests,...); 

一個示例代碼展示它是如何做:

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 
#include <math.h> 

int main(int argc, char *argv[]) { 

    MPI_Request requests[42]; 

    MPI_Init(&argc,&argv); 

    int size,rank; 
    MPI_Comm_size(MPI_COMM_WORLD,&size); 
    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 

    int version,subversion; 
    MPI_Get_version(&version, &subversion); 

    if(rank==0){printf("MPI version %d.%d\n",version,subversion);} 

    //dimensions 
    int nbscatter=5; 
    int nlocal=2; 
    double* array=NULL; 
    int i,j,k; 
    //build a 2D array of nbscatter lines and nlocal*size columns on root process 
    if(rank==0){ 
     array=malloc(nlocal*nbscatter*size*sizeof(double)); 
     if(array==NULL){printf("malloc failure\n");} 


     for(i=0;i<nbscatter;i++){ 
      for(j=0;j<size*nlocal;j++){ 
       array[i*size*nlocal+j]=j+0.01*i; 
       printf("%lf ",array[i*size*nlocal+j]); 
      } 
      printf("\n"); 
     } 

    } 

    //on each process, a 2D array of nbscatter lines and nlocal columns 
    double* arrayloc=malloc(nlocal*nbscatter*sizeof(double)); 
    if(arrayloc==NULL){printf("malloc failure2\n");} 

    //counts and displacements 
    int* displs; 
    int* scounts; 
    displs = malloc(nbscatter*size*sizeof(int)); 
    if(displs==NULL){printf("malloc failure\n");} 
    scounts = malloc(nbscatter*size*sizeof(int)); 
    if(scounts==NULL){printf("malloc failure\n");} 

    for(i=0;i<nbscatter;i++){ 
     for(j=0;j<size;j++){ 
      displs[i*size+j]=j*nlocal; 
      scounts[i*size+j]=nlocal; 
     } 

     // scatter the lines 
     if(rank==0){  
      MPI_Iscatterv(&array[i*nlocal*size], &scounts[i*size], &displs[i*size],MPI_DOUBLE,&arrayloc[i*nlocal], nlocal,MPI_DOUBLE, 0, MPI_COMM_WORLD, &requests[i]); 
     }else{ 
      MPI_Iscatterv(NULL, &scounts[i*size], &displs[i*size],MPI_DOUBLE,&arrayloc[i*nlocal], nlocal,MPI_DOUBLE, 0, MPI_COMM_WORLD, &requests[i]); 
     } 
    } 

    MPI_Status status[nbscatter]; 
    if(MPI_Waitall(nbscatter,requests,status)!=MPI_SUCCESS){ 
     printf("MPI_Waitall() failed\n"); 
    } 

    if(rank==0){ 
     free(array); 
    } 
    free(displs); 
    free(scounts); 

    //print the local array, containing the scattered columns 
    for(k=0;k<size;k++){ 
     if(rank==k){ 
      printf("on rank %d\n",k); 
      for(i=0;i<nbscatter;i++){ 
       for(j=0;j<nlocal;j++){ 
        printf("%lf ",arrayloc[i*nlocal+j]); 
       } 
       printf("\n"); 
      } 

     } 

     MPI_Barrier(MPI_COMM_WORLD); 
    } 

    free(arrayloc); 


    MPI_Finalize(); 



    return 0; 
} 

要通過mpicc main.c -o main -Wall編譯和mpirun -np 4 main

相關問題