在MPI中,如何编写下面的程序 等待所有计算完成
In MPI, how to make the following program Wait till all calculations are completed
我是 MPI 的新手,这个程序是用 C 语言编写的。在下面的程序中,我要求其他处理器打印消息。但是我想在完成所有这些其他过程后在 process/rank 0 处打印 "END" 消息。对于 运行 这个程序,我使用 4 个处理器并遵循命令 mpicc file.c -o objfile
和 mpirun -np 4 objfile
如果可能请给我举个例子。
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int i;
double centroid[3];/*ignore this array*/
if (world_rank == 0)
{
int destination;
for (i=0; i<3; i++)
{
/*Ignore centroid buffer been sent for now*/
destination = i+1;/*destination rank or process*/
MPI_Send(¢roid, 3, MPI_DOUBLE, destination, 0, MPI_COMM_WORLD);
}
printf("\nEND: This need to print after all MPI_Send/MPI_Recv has been completed\n\n");
}
else
{
MPI_Recv(¢roid, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
sleep(1); /*This represent many calculations that will happen here later, instead of sleep*/
printf("Printing at Rank/Process number: %d\n", world_rank);
}
MPI_Finalize();
return 0;
}
结果:
END: This need to print after all MPI_Send/MPI_Recv has been completed
Printing at Rank/Process number: 2
Printing at Rank/Process number: 3
Printing at Rank/Process number: 1
请修改此代码或举例说明如何等待所有这些其他处理器完成
好吧,你快到了。所缺少的只是对所有进程的 MPI_Barrier()
调用。这可以通过以下方式完成:
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int i;
double centroid[3];/*ignore this array*/
if (world_rank == 0)
{
int destination;
for (i=0; i<3; i++)
{
/*Ignore centroid buffer been sent for now*/
destination = i+1;/*destination rank or process*/
MPI_Send(¢roid, 3, MPI_DOUBLE, destination, 0, MPI_COMM_WORLD);
}
MPI_Barrier(MPI_COMM_WORLD);
printf("\nEND: This need to print after all MPI_Send/MPI_Recv has been completed\n\n");
}
else
{
MPI_Recv(¢roid, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
sleep(1); /*This represent many calculations that will happen here later, instead of sleep*/
printf("Printing at Rank/Process number: %d\n", world_rank);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
添加此障碍后,我的笔记本电脑上的代码为:
~/tmp$ mpirun -n 4 ./a.out
Printing at Rank/Process number: 1
Printing at Rank/Process number: 2
Printing at Rank/Process number: 3
END: This need to print after all MPI_Send/MPI_Recv has been completed
注意:在这种情况下,排名 1 到 3 的打印是有序的,但这只是偶然,因为这可能以任何顺序发生。实际上,上面的代码将保证在进程 #0 和其他进程之间调用 printf()
的顺序,但它不会保证打印到屏幕的顺序,因为缓冲等可能发生并且把事情搞砸了。
公平地说,它应该适用于大多数环境(大部分时间)。但严格来说,这并不能保证。
我是 MPI 的新手,这个程序是用 C 语言编写的。在下面的程序中,我要求其他处理器打印消息。但是我想在完成所有这些其他过程后在 process/rank 0 处打印 "END" 消息。对于 运行 这个程序,我使用 4 个处理器并遵循命令 mpicc file.c -o objfile
和 mpirun -np 4 objfile
如果可能请给我举个例子。
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int i;
double centroid[3];/*ignore this array*/
if (world_rank == 0)
{
int destination;
for (i=0; i<3; i++)
{
/*Ignore centroid buffer been sent for now*/
destination = i+1;/*destination rank or process*/
MPI_Send(¢roid, 3, MPI_DOUBLE, destination, 0, MPI_COMM_WORLD);
}
printf("\nEND: This need to print after all MPI_Send/MPI_Recv has been completed\n\n");
}
else
{
MPI_Recv(¢roid, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
sleep(1); /*This represent many calculations that will happen here later, instead of sleep*/
printf("Printing at Rank/Process number: %d\n", world_rank);
}
MPI_Finalize();
return 0;
}
结果:
END: This need to print after all MPI_Send/MPI_Recv has been completed
Printing at Rank/Process number: 2
Printing at Rank/Process number: 3
Printing at Rank/Process number: 1
请修改此代码或举例说明如何等待所有这些其他处理器完成
好吧,你快到了。所缺少的只是对所有进程的 MPI_Barrier()
调用。这可以通过以下方式完成:
#include <mpi.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
MPI_Init(&argc, &argv);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int i;
double centroid[3];/*ignore this array*/
if (world_rank == 0)
{
int destination;
for (i=0; i<3; i++)
{
/*Ignore centroid buffer been sent for now*/
destination = i+1;/*destination rank or process*/
MPI_Send(¢roid, 3, MPI_DOUBLE, destination, 0, MPI_COMM_WORLD);
}
MPI_Barrier(MPI_COMM_WORLD);
printf("\nEND: This need to print after all MPI_Send/MPI_Recv has been completed\n\n");
}
else
{
MPI_Recv(¢roid, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
sleep(1); /*This represent many calculations that will happen here later, instead of sleep*/
printf("Printing at Rank/Process number: %d\n", world_rank);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
添加此障碍后,我的笔记本电脑上的代码为:
~/tmp$ mpirun -n 4 ./a.out
Printing at Rank/Process number: 1
Printing at Rank/Process number: 2
Printing at Rank/Process number: 3
END: This need to print after all MPI_Send/MPI_Recv has been completed
注意:在这种情况下,排名 1 到 3 的打印是有序的,但这只是偶然,因为这可能以任何顺序发生。实际上,上面的代码将保证在进程 #0 和其他进程之间调用 printf()
的顺序,但它不会保证打印到屏幕的顺序,因为缓冲等可能发生并且把事情搞砸了。
公平地说,它应该适用于大多数环境(大部分时间)。但严格来说,这并不能保证。