【问题标题】:Runtime of MPI_Win_create at origin is increasing with increase in the size of the target windowMPI_Win_create 在原点的运行时间随着目标窗口大小的增加而增加
【发布时间】:2021-09-27 06:51:33
【问题描述】:

我刚刚开始学习 MPI,并且正在做一个实验,我正在测量 MPI_Win_create 的运行时间。我正在使用mpich 3.4.1 库。在这个实验中,我有两个进程 --- origin 和 target。我有以下代码行来测量运行时间:

     double startTime, endTime;
     startTime = MPI_Wtime();
     MPI_Win_create(buffer, bufferSize, sizeof(char), MPI_INFO_NULL, MPI_COMM_WORLD, win);
     endTime = MPI_Wtime();
     double winCreateTime = endTime - startTime;

在我的实验中,原始进程 (rank==0) 的 bufferSize 始终为零。但是,在目标进程(rank==1)中,我将缓冲区大小增加到大约 2GB。我在源进程和目标进程的运行时 MPI_Win_create 中看到以下趋势:

目标进程大约有 100MB 的 bufferSize,MPI_Win_create time = 2.21 在源进程,0.001071 在目标进程。目标进程大约 1GB 的 bufferSize,MPI_Win_create time = 25.21 在源进程,0.000894 在目标进程。在大约 2GB 处,我在原始进程 MPI_Win_create time = 41.580131 和目标进程 MPI_Win_create time = 0.000999 上看到了这一点。对于我尝试过的各种数据大小,这种趋势是相同的。也就是说,原始进程的 MPI_Win_create 时间始终高于目标进程(并且随着数据大小的增加而增加)。在目标进程中,它要低得多。

据我了解,在调用 MPI_Win_create 时,相应的进程会创建一个 RMA 窗口,该窗口会在相应进程的地址空间中公开内存区域,从buffer 指向的位置开始,该区域的大小为bufferSize .我无法理解为什么当目标进程的 bufferSize 增加时,MPI_Win_create 的运行时间会在源进程中增加。以及为什么在目标进程端 MPI_Win_create 的运行时间或多或少是恒定的,并且即使bufferSize 增加也非常小。源端发生了什么而目标端没有发生?

【问题讨论】:

  • 请上传您的测试用例。除了不平衡之外,持续时间似乎很长。
  • 哪种 MPI 实现以及您的平台是什么?
  • @GillesGouaillardet 我想我现在知道这种不平衡的原因了。 MPI_Win_create 似乎是一个集体函数调用,其中通信器中的所有进程进行通信并创建一个 MPI 窗口。因此,到达此函数调用的任何进程似乎都被阻止,其他参与进程也无法在各自的代码中到达这一点(正确吗??)。就我而言,目标进程在调用 MPI_Win_create 之前正在生成大量数据。然而,在这一点之前,起源做的工作很少。所以对于origin,startTime的点比Target早得多。
  • 所以,我在原点的endTime - startTime似乎也包含了目标进程的数据生成时间,因为它需要等待目标进程完成数据生成并到达其对应的MPI_Win_create。但是,目标方endTime - startTime 似乎是目标在其 MPI_Win_create 上花费的实际时间。
  • @VictorEijkhout 我在 CentOS 7.7.1908 (x86_64) 上使用 mpich 3.4.1 实现

标签: c++ performance parallel-processing mpi mpich


【解决方案1】:

回答我自己的问题。经过深入挖掘,我发现源进程和目标进程之间运行时不平衡的原因是由于在测量开始时间之前缺乏同步。

MPI_Win_create 是一个集合函数调用,通信器中的所有进程在该函数调用中进行通信并创建一个 MPI 窗口。因此,到达此函数调用的任何进程似乎都被阻止,其他参与进程也无法在其各自的代码中到达这一点。在我的例子中,目标进程在调用 MPI_Win_create 之前正在生成大量数据。然而,在这一点之前,起源做的工作很少。因此,对于原点,startTime 的点比目标点要早得多。所以我在源进程的endTime - startTime也包含了目标进程的数据生成时间,因为它需要等待目标进程完成数据生成并到达其对应的MPI_Win_create。但是,在目标端,endTime - startTime 是目标在其 MPI_Win_create 上花费的实际时间。

解决方案:我能够在测量 startTime 之前使用 MPI_Barrier() 获得合理的运行时间,如下面的模型代码 sn-p 所示。 通过此更改,对于大约 2GB 的缓冲区大小,我在大约 0.000347 秒的原始进程和大约 0.000382 秒的目标进程处获得 MPI_Win_create 运行时。

#include <mpi.h>

#define ORIGIN 0
#define TARGET 1

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

    MPI_Init(&argc, &argv);

    int my_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    double startTime, endTime;

    char *buffer = nullptr;
    long bufferSize = 0;
    if (my_rank == TARGET) {
        bufferSize = 2000000000;
        buffer = new char[bufferSize](); //OR, getLargeData()
    }

    MPI_Barrier(MPI_COMM_WORLD);

    MPI_Win window;

    startTime = MPI_Wtime();

    MPI_Win_create(buffer, bufferSize, sizeof(char), MPI_INFO_NULL, MPI_COMM_WORLD, &window);

    endTime = MPI_Wtime();

    MPI_Win_fence(0, window);

    printf("\nMPI_Win_create time at %s = %lf", (my_rank == ORIGIN)?"ORIGIN":"TARGET", endTime-startTime);

    MPI_Win_free(&window);

    if (buffer) delete[] buffer;

    MPI_Finalize();
}

【讨论】:

  • 有趣的场景。是的,在你计时的事情之前和之后设置障碍通常是个好主意。
  • @VictorEijkhout 感谢您的确认。
猜你喜欢
  • 2019-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-01
  • 2020-01-06
  • 1970-01-01
  • 2018-06-28
相关资源
最近更新 更多