C MPI#U屏障不';重新排序printf(stdout)消息似乎不起作用
下面是一个非常基本的MPI程序 或者类似的事情(问候和道别应该分组,但不能保证过程顺序) 以下是我的实际输出:C MPI#U屏障不';重新排序printf(stdout)消息似乎不起作用,c,mpi,C,Mpi,下面是一个非常基本的MPI程序 或者类似的事情(问候和道别应该分组,但不能保证过程顺序) 以下是我的实际输出: 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_屏障应该做什么吗?据我所知,如果我只使用一次,那么它会给我预期的结果,但除此之外,它似乎什么也没做 我知道以前有人问过很多
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_屏障应该做什么吗?据我所知,如果我只使用一次,那么它会给我预期的结果,但除此之外,它似乎什么也没做
我知道以前有人问过很多类似的问题,但我看到的问题中的提问者误解了MPI_屏障的功能
问候和告别应该分组
不应该,在printf
函数中有额外的(MPI异步)缓冲,另一个缓冲是stdout
从多个MPI进程收集到单用户终端
printf
只打印到libc(glibc)的内存缓冲区中,有时会刷新到真实的文件描述符(stdout
;使用fflush
刷新缓冲区);而fprintf(stderr,…)
通常比stdout
远程任务由mpirun/mpiexec启动,通常使用ssh
remoteshell,它执行stdout
/stderr
转发ssh
(以及TCP)将缓冲数据,并且当来自ssh
的数据通过mpirun/mpiexec或其他实体(多个数据流被多路复用为一个)显示在终端上时,可以重新排序
您得到的结果就像第一个进程中的4个字符串在其出口处被缓冲和刷新(所有字符串都被打印到stdout
,通常有几千字节的缓冲区);第二个进程的另外4个字符串也被缓冲,直到退出。所有4个字符串都通过ssh
或其他启动方法以单个“数据包”的形式发送到您的控制台,您的控制台仅以某种顺序显示4行的两个数据包,即“4行数据包来自\u id\u 0;4行数据包来自\u id\u 1”;或“4行数据包来自\u id\u 1;4行数据包来自\u id\u 0;”
MPI_屏障应该做什么
MPI\u Barrier
同步部分代码,但它不能在libc/glibc打印和文件I/O功能中禁用任何缓冲,也不能在ssh
或其他远程shell中禁用任何缓冲
如果您的所有进程都在具有同步系统时钟的机器上运行(当您有一台机器时,它们将是,当集群上有ntpd
时,它们应该是),您可以向每个printf
添加时间戳字段,以检查实际顺序是否符合您的屏障(gettimeofday
查找当前时间,并且没有额外的缓冲)。即使printf
和ssh
将对消息重新排序,也可以对时间戳输出进行排序
#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;
}
#包括
#包括
#包括
无效打印时间戳消息(int mpi等级,字符*s);
{
现在构造timeval;
gettimeofday(&now,NULL);
printf(“[%u.%06u](%d):%s\n”,now.tv\u sec,now.tv\u usec,mpi\u rank,s);
}
int main(int argc,char*argv[]){
整数秩;
整数大小;
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
MPI_屏障(MPI_通信世界);
打印带有时间戳的消息(排名,“第一你好”);
MPI_屏障(MPI_通信世界);
打印带有时间戳的消息(排名,“第一次再见”);
MPI_屏障(MPI_通信世界);
打印带有时间戳的消息(排名,“第二你好”);
MPI_屏障(MPI_通信世界);
打印带有时间戳的消息(排名,“第二再见”);
MPI_Finalize();
返回0;
}
我认为关于gettimeofday
的假设在许多分布式系统上都不成立。NTP绝对不够精确。如果您必须进行一些排序,只需在每个屏障上增加一个计数器。祖兰,屏障有多快,在典型集群中NTP有多精确?屏障通常为10-100 us(),NTP在理想条件下有1ms左右()。@Zulan,我想你是对的。我已将我的问题标记为重复。
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
#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;
}