首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将MPI_Reduce转换为MPI_Send和MPI_Recv?

如何将MPI_Reduce转换为MPI_Send和MPI_Recv?
EN

Stack Overflow用户
提问于 2021-02-04 01:36:38
回答 1查看 135关注 0票数 0

我正在开发一个并行处理程序,它使用MPI_Send()和MPI_Recv()而不是MPI_Reduce()。我知道MPI_Send()需要从每个处理器向根处理器发送一个值,也就是0,而MPI_Recv()需要从每个处理器接收所有值。

我一直收到错误,其中Send中的值将不会发送到接收端,从而使最终值为0。MPI_Reduce()函数仍然在代码中,但是注释掉了,看看需要替换什么。有人能帮上忙吗?

代码语言:javascript
复制
#include "mpi.h"
#include <stdio.h>
#include <math.h>
 
int main( int argc, char *argv[])
{
    int n, i;
    double PI25DT = 3.141592653589793238462643;
    double pi, h, sum, x;
 
    int numprocs, myid;
    double startTime, endTime;
 
    /* Initialize MPI and get number of processes and my number or rank*/
    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myid);
 
    /* Processor zero sets the number of intervals and starts its clock*/
    if (myid==0) {
       n=600000000;
       startTime=MPI_Wtime();
       for (int i = 0; i < numprocs; i++) {
           if (i != myid) {
               MPI_Send(&n, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
           }
       }
    } 
    else {
        MPI_Recv(&n, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }
 
    /* Calculate the width of intervals */
    h   = 1.0 / (double) n;
 
    /* Initialize sum */
    sum = 0.0;
    /* Step over each inteval I own */
    for (i = myid+1; i <= n; i += numprocs) {
        /* Calculate midpoint of interval */
        x = h * ((double)i - 0.5);
        /* Add rectangle's area = height*width = f(x)*h */
        sum += (4.0/(1.0+x*x))*h;
    }
    /* Get sum total on processor zero */
    //MPI_Reduce(&sum,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
    double value = 0;
    if (myid != 0) {
            MPI_Send(&sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
    }
    else {
        for (int i = 1; i < numprocs; i++) {
            MPI_Recv(&value, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            pi += value;
            }
    }
    
    /* Print approximate value of pi and runtime*/
    if (myid==0) {
       printf("pi is approximately %.16f, Error is %e\n",
                       pi, fabs(pi - PI25DT));
       endTime=MPI_Wtime();
       printf("runtime is=%.16f",endTime-startTime);
    }
    MPI_Finalize();
    return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2021-02-04 03:23:55

您正在使用MPI_INT发送double类型的值

代码语言:javascript
复制
if (myid != 0) {
  MPI_Send(&sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
  //                ^^^^^^^
}

int为4字节长;double为8字节长。尽管接收操作成功了,但它不能构造MPI_DOUBLE类型的值,因为消息中只有4个字节,所以它不会向value中写入任何内容,它仍然是0.0。实际上,如果您替换:

代码语言:javascript
复制
MPI_Recv(&value, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

使用

代码语言:javascript
复制
MPI_Status status;
int count;

MPI_Recv(&value, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &count);
if (count == MPI_UNDEFINED) {
  printf("Short message received\n");
  MPI_Abort(MPI_COMM_WORLD, 0);
}

您的程序将中止,这表明条件语句体是由于MPI_Get_count()count中返回MPI_UNDEFINED而执行的,这表明收到的消息长度不是MPI_DOUBLE大小的整数倍。

此外,在接收循环之前,必须将pi显式初始化为sum,否则您将由于以下错误之一而获得错误的pi值:

  • pi保持未初始化,并且具有任意初始值,并且
  • 排名0的贡献不会添加到最终结果中。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66032754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档