【问题标题】:How does MPI_Barrier() work?MPI_Barrier() 是如何工作的?
【发布时间】:2016-09-20 22:47:30
【问题描述】:

我有这个代码:

#include <cstdint>
#include <mpi.h>
#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (rank == 0)
        MPI_Barrier(MPI_COMM_WORLD);
    cout << "Some output\n";
    if (rank == 1)
        MPI_Barrier(MPI_COMM_WORLD);
    MPI_Barrier(MPI_COMM_WORLD);
    cout << "end\n";
    MPI_Finalize();
    return 0;
}

当我运行时

mpiexec -n 2 MPI.exe

程序有效;输出是:

Some output
End
Some output
End

但是,当我以

身份运行时

mpiexec -n 3 MPI.exe

程序没有正常工作。我期望这样的输出:

rank 3 - Some_output
rank 2 - Some output
rank 3 - End
rank 0 - Some output

在这一步,我希望程序停止。

【问题讨论】:

标签: mpi


【解决方案1】:

您需要确保每个进程的屏障调用次数相同。在您的特定情况下,当 n=3 时,您对 0 级和 1 级有两个屏障调用,但对于 2 级只有 1 个调用。程序将阻塞,直到 2 级进程也达到屏障。

n=3 的情况如下:

together:
    rank 0 will reach barrier 1 then block
    rank 1 will print "some output", reach barrier 2 then block
    rank 2 will print "some output", reach barrier 3 then block
together:
    rank 0 will print "some output", reach barrier 3 then block
    rank 1 will reach barrier 3 then block
    rank 2 will print "end" then hit finalize

让一个进程完成而其他进程被阻止将是未定义的行为。


对 n=2 进行同样的分析:

together:
    rank 0 will reach barrier 1 then block
    rank 1 will print "some output", reach barrier 2 then block
together:
    rank 0 will print "some output", reach barrier 3 then block
    rank 1 will reach barrier 3 then block
together:
    rank 0 will print "end" then hit finalize
    rank 1 will print "end" then hit finalize

这表明输出应该是:

some output
some output
end 
end

无论你得到什么:

some output
end 
some output
end

这与 mpi 基础设施如何缓存来自各个等级的标准输出传输有关。如果我们引入延迟以便 MPI 决定它应该收集结果,我们可以更好地看到行为:

#include <cstdint>
#include <unistd.h>
#include <mpi.h>
#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (rank == 0) {
        cout << rank << " Barrier 1\n" << flush;
        MPI_Barrier(MPI_COMM_WORLD);
    }
    cout << rank << " Some output \n" << flush;
    usleep(1000000);
    if (rank == 1) {
        cout << rank << " Barrier 2\n" << flush;
        MPI_Barrier(MPI_COMM_WORLD);
    }
    cout << rank << " Barrier 3\n" << flush;
    MPI_Barrier(MPI_COMM_WORLD);
    cout << rank << " end\n" << flush;
    usleep(1000000);
    MPI_Finalize();
    return 0;
}

产生:

$ mpiexec -n 2 ./a.out 
0 Barrier 1
1 Some output 
0 Some output 
1 Barrier 2
1 Barrier 3
0 Barrier 3
0 end
1 end

$ mpiexec -n 3 ./a.out 
2 Some output 
0 Barrier 1
1 Some output 
0 Some output 
1 Barrier 2
1 Barrier 3
2 Barrier 3
2 end
0 Barrier 3
^Cmpiexec: killing job...

或者,查看以下 C++11 代码中的时间戳:

#include <cstdint>
#include <chrono>
#include <mpi.h>
#include <iostream>
using namespace std;

inline unsigned long int time(void) { 
    return std::chrono::high_resolution_clock::now().time_since_epoch().count(); 
}

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (rank == 0) {
        MPI_Barrier(MPI_COMM_WORLD);
    }
    cout << rank << " " << time() << " Some output\n";
    if (rank == 1) {
        MPI_Barrier(MPI_COMM_WORLD);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    cout << rank << " " << time() << " end\n";
    MPI_Finalize();
    return 0;
}

输出:

$ mpiexec -n 2 ./a.out 
0 1464100768220965374 Some output
0 1464100768221002105 end
1 1464100768220902046 Some output
1 1464100768221000693 end

按时间戳排序:

$ mpiexec -n 2 ./a.out 
1 1464100768220902046 Some output
0 1464100768220965374 Some output
1 1464100768221000693 end
0 1464100768221002105 end

结论是 Barrier 的行为符合预期,打印语句不一定会告诉您。

编辑:2016-05-24 以显示对程序行为的详细分析。

【讨论】:

  • 程序会阻塞,但是为什么我没有从rank 3输出?我希望排名 3 会打印“一些输出”,但没有发生。
  • @van9petryk,我添加了更详细的分析。对于我的特定设置,它确实在我按 Ctrl-C 杀死程序之前捕获了 2 级的输出。如果您的 mpi 在 rank 2 处于 finalize 并且其他 rank 处于障碍时立即失败,则可能不会费心收集 rank 2 标准输出。
猜你喜欢
  • 2011-06-21
  • 2012-01-04
  • 2012-05-15
  • 2023-04-07
  • 2014-01-17
  • 2013-07-08
  • 2011-10-14
  • 2011-01-04
  • 2011-07-08
相关资源
最近更新 更多