2016-01-23 20 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

相关问题