gpt4 book ai didi

c - MPI_Barrier 似乎不起作用,重新排序 printf (stdout) 消息

转载 作者:行者123 更新时间:2023-11-30 14:59:27 31 4
gpt4 key购买 nike

下面是一个非常基本的 MPI 程序

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

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

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

MPI_Barrier(MPI_COMM_WORLD);
printf("Hello from %d\n", rank);
MPI_Barrier(MPI_COMM_WORLD);
printf("Goodbye from %d\n", rank);
MPI_Barrier(MPI_COMM_WORLD);
printf("Hello 2 from %d\n", rank);
MPI_Barrier(MPI_COMM_WORLD);
printf("Goodbye 2 from %d\n", rank);
MPI_Finalize();
return 0;
}

您期望输出为(2 个进程)

Hello from 0
Hello from 1
Goodbye from 1
Goodbye from 0
Hello 2 from 1
Hello 2 from 0
Goodbye 2 from 0
Goodbye 2 from 1

或者类似的东西(你好和再见应该分组,但不保证流程顺序)。

这是我的实际输出:

Hello from 0
Goodbye from 0
Hello 2 from 0
Goodbye 2 from 0
Hello from 1
Goodbye from 1
Hello 2 from 1
Goodbye 2 from 1

我是否从根本上误解了 MPI_Barrier 应该做什么?据我所知,如果我只使用它一次,那么它会给我预期的结果,但除此之外,它似乎绝对没有任何作用。

我意识到以前有人问过很多类似的问题,但我查看的问题中的提问者误解了 MPI_Barrier 的功能。

最佳答案

the hellos and goodbyes should be grouped

他们不应该,printf函数内部有额外的(MPI异步)缓冲,另一个缓冲是从多个MPI进程收集到单个用户终端的stdout

printf 只是打印到 libc (glibc) 的内存缓冲区中,有时会刷新到真实文件描述符(stdout;使用 fflush) > 刷新缓冲区);和 fprintf(stderr,...) 通常比 stdout

具有更少的缓冲

远程任务由 mpirun/mpiexec 启动,通常使用 ssh 远程 shell,它执行 stdout/stderr 转发。 ssh(以及 TCP)将缓冲数据,并且当 mpirun/mpiexec 或其他实体在您的终端显示来自 ssh 的数据时,可以重新排序(多个数据流被复用)合二为一)。

你得到的就像是第一个进程的 4 个字符串在其退出时被缓冲和刷新(所有字符串都被打印到 stdout ,通常有几千字节的缓冲区);来自第二个进程的另外 4 个字符串也被缓冲,直到退出。所有 4 个字符串均通过 ssh 或其他启动方法作为单个“数据包”发送到您的控制台,并且您的控制台仅按某种顺序显示 4 行数据包,每个数据包为“4_lines_packet_from_id_0; 4_lines_packet_from_id_1;”或“4_lines_packet_from_id_1;4_lines_packet_from_id_0;”。

MPI_Barrier is supposed to do?

MPI_Barrier 同步部分代码,但它无法禁用 libc/glibc 打印和文件 I/O 函数中的任何缓冲,也不能禁用 ssh 或其他远程 shell 中的任何缓冲.

如果您的所有进程都在具有同步系统时钟的机器上运行(当您只有单台机器时,它们应该是在集群上有 ntpd 时),您可以将时间戳字段添加到每个 printf 来检查真实订单是否符合您的屏障(gettimeofday 查找当前时间,并且没有额外的缓冲)。即使 printfssh 会对消息重新排序,您也可以对带时间戳的输出进行排序。

#include <mpi.h>
#include <sys/time.h>
#include <stdio.h>

void print_timestamped_message(int mpi_rank, char *s);
{
struct timeval now;
gettimeofday(&now, NULL);
printf("[%u.%06u](%d): %s\n", now.tv_sec, now.tv_usec, mpi_rank, s);
}

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

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

MPI_Barrier(MPI_COMM_WORLD);
print_timestamped_message(rank, "First Hello");
MPI_Barrier(MPI_COMM_WORLD);
print_timestamped_message(rank, "First Goodbye");
MPI_Barrier(MPI_COMM_WORLD);
print_timestamped_message(rank, "Second Hello");
MPI_Barrier(MPI_COMM_WORLD);
print_timestamped_message(rank, "Second Goodbye");
MPI_Finalize();
return 0;
}

关于c - MPI_Barrier 似乎不起作用,重新排序 printf (stdout) 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42743100/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com