0

我正在尝试编写自己的 MPI 函数,该函数将计算向量中的最小数字并将其广播给所有进程。我将这些过程视为二叉树,并在从叶子移动到根时找到最小值。然后我通过它的孩子从根向叶子发送消息。但是,当我尝试从进程等级 1 的左孩子(进程等级 3)接收最小值时,我遇到了分段错误,执行中只有 4 个进程从 0 到 3。

void Communication::ReduceMin(double &partialMin, double &totalMin)
{
    MPI_Barrier(MPI_COMM_WORLD);
    double *leftChild, *rightChild;
    leftChild = (double *)malloc(sizeof(double));
    rightChild = (double *)malloc(sizeof(double));
    leftChild[0]=rightChild[0]=1e10;
    cout<<"COMM REDMIN: "<<myRank<<" "<<partialMin<<" "<<nProcs<<endl;
    MPI_Status *status;
    //MPI_Recv from 2*i+1 amd 2*i+2
    if(nProcs > 2*myRank+1)
    {
        cout<<myRank<<" waiting from "<<2*myRank+1<<" for "<<leftChild[0]<<endl;
        MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, MPI_COMM_WORLD, status);             //SEG FAULT HERE
        cout<<myRank<<" got from "<<2*myRank+1<<endl;
    }
    if(nProcs > 2*myRank+2)
    {
        cout<<myRank<<" waiting from "<<2*myRank+2<<endl;
        MPI_Recv((void *)rightChild, 1, MPI_DOUBLE, 2*myRank+2, 2*myRank+2, MPI_COMM_WORLD, status);
        cout<<myRank<<" got from "<<2*myRank+1<<endl;
    }
    //sum it up
    cout<<myRank<<" finding the min"<<endl;
    double myMin = min(min(leftChild[0], rightChild[0]), partialMin);
    //MPI_Send to (i+1)/2-1
    if(myRank!=0)
    {
        cout<<myRank<<" sending "<<myMin<<" to "<<(myRank+1)/2 -1 <<endl;
        MPI_Send((void *)&myMin, 1, MPI_DOUBLE, (myRank+1)/2 - 1, myRank, MPI_COMM_WORLD);
    }

    double min;
    //MPI_Recv from (i+1)/2-1
    if(myRank!=0)
    {
        cout<<myRank<<" waiting from "<<(myRank+1)/2-1<<endl;
        MPI_Recv((void *)&min, 1, MPI_DOUBLE, (myRank+1)/2 - 1, (myRank+1)/2 - 1, MPI_COMM_WORLD, status);
        cout<<myRank<<" got from "<<(myRank+1)/2-1<<endl;
    }
    totalMin = min;
    //MPI_send to 2*i+1 and 2*i+2
    if(nProcs > 2*myRank+1)
    {
        cout<<myRank<<" sending to "<<2*myRank+1<<endl;
        MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+1, myRank, MPI_COMM_WORLD);
    }
    if(nProcs > 2*myRank+2)
    {
        cout<<myRank<<" sending to "<<2*myRank+1<<endl;
        MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+2, myRank, MPI_COMM_WORLD);
    }
}

PS:我知道我可以使用

MPI_Barrier(MPI_COMM_WORLD);
MPI_Reduce((void *)&partialMin, (void *)&totalMin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
MPI_Bcast((void *)&totalMin, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

但我想写我自己的代码来娱乐。

4

1 回答 1

0

错误在于您在接收调用中使用状态参数的方式。您只需传递一个未初始化的指针,而不是传递实例的地址,MPI_Status这会导致崩溃:

MPI_Status *status; // status declared as a pointer and never initialised
...
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1,
         MPI_COMM_WORLD, status); // status is an invalid pointer here

您应该将代码更改为:

MPI_Status status;
...
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1,
         MPI_COMM_WORLD, &status);

由于您根本不检查代码中的所有状态,因此您可以简单地传递MPI_STATUS_IGNORE所有调用:

MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1,
         MPI_COMM_WORLD, MPI_STATUS_IGNORE);
于 2013-06-23T11:27:33.633 回答