Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用非阻塞运算计算数组和_C++_Mpi_Mpich - Fatal编程技术网

C++ 用非阻塞运算计算数组和

C++ 用非阻塞运算计算数组和,c++,mpi,mpich,C++,Mpi,Mpich,每个进程都需要计算其部分和并将其发送到0进程,然后计算数组的和 我写了这段代码 双*a; a=新的双精度[N]; 对于int i=0;i=N iend=ibeg-1; else ifiend>=N iend=N-1; 双s=0; 对于int i=ibeg;简而言之,您需要在分配reqs后立即将其所有元素设置为MPI_REQUEST_NULL 较长的答案是,MPI程序作为一个或多个源程序的多个实例运行,每个实例级别都有自己的一组不共享的变量。如果您有: if (proc_this != 0

每个进程都需要计算其部分和并将其发送到0进程,然后计算数组的和 我写了这段代码

双*a; a=新的双精度[N]; 对于int i=0;i=N iend=ibeg-1; else ifiend>=N iend=N-1; 双s=0;
对于int i=ibeg;简而言之,您需要在分配reqs后立即将其所有元素设置为MPI_REQUEST_NULL

较长的答案是,MPI程序作为一个或多个源程序的多个实例运行,每个实例级别都有自己的一组不共享的变量。如果您有:

    if (proc_this != 0)
        MPI_Isend(&s, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &reqs[proc_this]);
    else
        for (int i = 1; i < proc_count; i++) 
            MPI_Irecv(&inmes[i], 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &reqs[0]);
事实是,您将拥有:

reqs in rank 0: [ Irecv req |    ???    |    ???    | ... ??? ... ]
reqs in rank 1: [    ???    | Isend req |    ???    | ... ??? ... ]
reqs in rank 2: [    ???    |    ???    | Isend req | ... ??? ... ]
etc.
哪里???表示未初始化的内存。MPI_Waitall是一个本地操作,它只查看请求的本地副本。它无法完成其他列组发布的请求

未初始化的内存中可以有任何值,如果该值导致无效的请求句柄,MPI_Waitall将因错误而中止。如果将所有请求设置为MPI_REQUEST_NULL,则不会发生这种情况,因为会忽略NULL请求

代码中还有一个语义错误:

MPI_Irecv(&inmes[i], 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &reqs[0]);
将所有接收请求存储在同一位置,每个新请求都会覆盖上一个请求。因此,除了最后一个请求,您永远无法等待任何请求

假设您在MPI发送后立即调用MPI_Waitall,那么使用非阻塞发送就没有意义了。更干净的代码版本是:

    if (proc_this != 0)
        MPI_Send(&s, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
    else {
        MPI_Request* reqs = new MPI_Request[proc_count - 1];
        for (int i = 1; i < proc_count; i++) 
            MPI_Irecv(&inmes[i], 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &reqs[i-1]);
        MPI_Waitall(proc_count-1, reqs, MPI_STATUSES_IGNORE);
        delete [] reqs;
    }

我投票赞成关闭这个问题,因为错误不是C++…也许是MPI?如果你能提供一个简单的答案,你就更有可能得到答案。我不确定你发布的代码是否足以重现错误,因为我不熟悉MPI。@2785528我认为这不是投票结束问题的正当理由IRECV将在调用waitall后完成,所以在未初始化使用waitall调用MPI_waitall reqs后,您需要对收到的值求和。更好的版本是只使用MPI_Gather:-
MPI_Irecv(&inmes[i], 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &reqs[0]);
    if (proc_this != 0)
        MPI_Send(&s, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
    else {
        MPI_Request* reqs = new MPI_Request[proc_count - 1];
        for (int i = 1; i < proc_count; i++) 
            MPI_Irecv(&inmes[i], 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &reqs[i-1]);
        MPI_Waitall(proc_count-1, reqs, MPI_STATUSES_IGNORE);
        delete [] reqs;
    }