使用相同的通信器连续调用MPI_IScatterv

时间:2016-01-23 08:52:24

标签: c mpi nonblocking

我正在尝试使用非阻塞版本的通信,在同一个通信器上将两个不同的独立数组从0级分散到所有其他数组。

这些方面的东西:

foreach ($articles as $k=>$article) {
    if (!$this->isGranted('VIEW', $article)) {
        unset($articles[$k]);
    }
}

所以...是否可能(或者更确切地说,如果保证总是没有错误)使用相同的通信器连续两次调用MPI_IScatterv,或者可能影响结果 - 弄乱来自两个分散的消息,因为没有标签?

1 个答案:

答案 0 :(得分:1)

是的,根据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

运行