【问题标题】:Anomalous MPI behavior异常 MPI 行为
【发布时间】:2017-02-21 16:28:37
【问题描述】:

我想知道是否有人可以提供解释。

我将从代码开始:

/*
Barrier implemented using tournament-style coding
*/

// Constraints: Number of processes must be a power of 2, e.g.
// 2,4,8,16,32,64,128,etc.

#include <mpi.h>
#include <stdio.h>
#include <unistd.h>

void mybarrier(MPI_Comm);

// global debug bool
int verbose = 1;

int main(int argc, char * argv[]) {
    int rank;
    int size;

  int i;
  int sum = 0;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    int check = size;

    // check to make sure the number of processes is a power of 2
    if (rank == 0){
        while(check > 1){
            if (check % 2 == 0){
                check /= 2;
            } else {
                printf("ERROR: The number of processes must be a power of 2!\n");
                MPI_Abort(MPI_COMM_WORLD, 1);
                return 1;
            }
        }
    }

    // simple task, with barrier in the middle
  for (i = 0; i < 500; i++){
    sum ++;
  }
  mybarrier(MPI_COMM_WORLD);
  for (i = 0; i < 500; i++){
    sum ++;
  }

    if (verbose){
        printf("process %d arrived at finalize\n", rank);
    }
    MPI_Finalize();
    return 0;
}

void mybarrier(MPI_Comm comm){
    // MPI variables
  int rank;
  int size;

    int * data;

    MPI_Status * status;

    // Loop variables
  int i;
    int a;

    int skip;

    int complete = 0;
    int currentCycle = 1;

    // Initialize MPI vars
  MPI_Comm_rank(comm, &rank);
    MPI_Comm_size(comm, &size);

    // step 1, gathering
    while (!complete){
        skip = currentCycle * 2;

        // if currentCycle divides rank evenly, then it is a target
        if ((rank % currentCycle) == 0){
            // if skip divides rank evenly, then it needs to receive
            if ((rank % skip) == 0){
                MPI_Recv(data, 0, MPI_INT, rank + currentCycle, 99, comm, status);
                if (verbose){
                    printf("1: %d from %d\n", rank, rank + currentCycle);
                }
            // otherwise, it needs to send. Once sent, the process is done
            } else {
                if (verbose){
                    printf("1: %d to %d\n", rank, rank - currentCycle);
                }
                MPI_Send(data, 0, MPI_INT, rank - currentCycle, 99, comm);
                complete = 1;
            }
        }

        currentCycle *= 2;

        // main process will never send, so this code will allow it to complete
        if (currentCycle >= size){
            complete = 1;
        }
    }

    complete = 0;
    currentCycle = size / 2;

    // step 2, scattering

    while (!complete){
        // if currentCycle is 1, then this is the last loop
        if (currentCycle == 1){
            complete = 1;
        }

        skip = currentCycle * 2;

        // if currentCycle divides rank evenly then it is a target
        if ((rank % currentCycle) == 0){
            // if skip divides rank evenly, then it needs to send
            if ((rank % skip) == 0){
                if (verbose){
                    printf("2: %d to %d\n", rank, rank + currentCycle);
                }
                MPI_Send(data, 0, MPI_INT, rank + currentCycle, 99, comm);
            // otherwise, it needs to receive
            } else {
                if (verbose){
                    printf("2: %d waiting for %d\n", rank, rank - currentCycle);
                }
                MPI_Recv(data, 0, MPI_INT, rank - currentCycle, 99, comm, status);
                if (verbose){
                    printf("2: %d from %d\n", rank, rank - currentCycle);
                }
            }
        }

        currentCycle /= 2;
    }
}

预期行为

代码是将 sum 增加到 500,等待所有其他进程使用阻塞 MPI_Send 和 MPI_Recv 调用到达该点,然后将 sum 增加到 1000。

观察到的集群行为

集群按预期运行

在我的机器上观察到异常行为

main函数中的所有进程都报告为99,我已经专门链接到mybarrier的第二个while循环的标签。

另外

我的初稿是使用 for 循环编写的,使用该循环,程序也可以在集群上按预期执行,但在我的机器上执行永远不会完成,即使所有进程都调用 MPI_Finalize(但没有一个超出它)。

MPI 版本

我的机器正在运行 OpenRTE 2.0.2 集群正在运行 OpenRTE 1.6.3

问题

我观察到我的机器似乎一直在意外运行,而集群却正常执行。我编写的其他 MPI 代码也是如此。 1.6.3 和 2.0.2 之间是否有我不知道的重大变化?

无论如何,我很困惑,我想知道是否有人可以解释为什么我的机器似乎无法正确运行 MPI。我希望我提供了足够的详细信息,但如果没有,我很乐意提供您需要的任何其他信息。

【问题讨论】:

    标签: mpi


    【解决方案1】:

    您的代码有问题,这可能是导致您看到的奇怪行为的原因。

    您正在向MPI_Recv 例程传递一个尚未分配的status 对象。事实上,该指针甚至没有被初始化,所以如果它碰巧不是NULLMPI_Recv 将最终写入内存中的任何位置,从而导致未定义的行为。正确的形式如下:

    MPI_Status status;
    ...
    MPI_Recv(..., &status);
    

    或者如果你想使用堆:

    MPI_Status *status = malloc(sizeof(MPI_Status));
    ...
    MPI_Recv(..., status);
    ...
    free(status);
    

    此外,由于您没有使用接收返回的值,因此您应该改用MPI_STATUS_IGNORE

    MPI_Recv(..., MPI_STATUS_IGNORE);
    

    【讨论】:

    • 我相信已经解决了。谢谢你的帮助。我是 MPI 的新手,所以我仍在尝试弄清楚一切是如何工作的。
    猜你喜欢
    • 2011-11-30
    • 1970-01-01
    • 2012-09-20
    • 2019-09-22
    • 1970-01-01
    • 2012-12-05
    • 2017-01-22
    • 2013-04-14
    • 2014-01-29
    相关资源
    最近更新 更多