如何检查非阻塞减少的完成情况?
How to check completion of non-blocking reduce?
我不清楚如何在 MPI 中正确使用非阻塞集合,特别是 MPI_Ireduce()
在这种情况下:
假设我想从根等级中收集一笔款项:
int local_cnt;
int total_cnt;
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
/* now I want to check if the reduce is finished */
if (rank == 0) {
int flag = 0;
MPI_Status status;
MPI_Test(&request, &flag, &status);
if (flag) {
/* reduce is finished? */
}
}
这是检查非阻塞 reduce 是否完成的正确方法吗?我的困惑来自两个方面:第一,根进程是否可以或应该使用 MPI_Test()
检查它,因为这只对根有意义?其次,由于 MPI_Test()
是本地操作,这个本地操作如何知道操作完成?它确实需要完成所有进程,对吧?
您必须检查所有参与等级是否完成,而不仅仅是根。
从用户的角度来看,您需要了解通信的完成情况,因为您不能对提供给非阻塞操作的内存做任何事情。 IE。如果你发送一个像 local_cnt
这样的局部作用域变量,你不能在确认操作完成之前写入它或离开它的作用域。
确保完成的一个选项是调用 MPI_Test
,直到它最终 returns flag==true
。仅当您可以在对 MPI_Test
:
的调用之间做一些有用的事情时才使用它
{
int local_cnt;
int total_cnt;
// fill local_cnt on all ranks
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
int flag;
do {
// perform some useful computation
MPI_Status status;
MPI_Test(&request, &flag, &status);
} while (!flag)
}
如果您在两次调用之间无事可做,请不要循环调用 MPI_Test
。而是使用 MPI_Wait
,它会阻塞直到完成。
{
int local_cnt;
int total_cnt;
// fill local_cnt on all ranks
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
// perform some useful computation
MPI_Status status;
MPI_Wait(&request, &status);
}
请记住,如果您根本没有有用的计算,并且由于死锁原因不需要非阻塞,请首先使用阻塞通信。如果您有多个正在进行的非阻塞通信,则有 MPI_Waitany
、MPI_Waitsome
、MPI_Waitall
及其测试变体。
Zulan 出色地回答了您问题的第一部分。
MPI_Reduce()
returns 当
- 可以在非根等级上覆盖发送缓冲区
- 结果在根等级上可用(这意味着所有等级都已完成)
所以非根等级无法知道根等级是否完成。如果你确实需要这些信息,那么你需要手动添加一个MPI_Barrier()
。也就是说,您通常 不需要 需要此信息,如果您认为您确实需要它,则您的应用可能有问题。
如果您使用非阻塞集合(例如 MPI_Wait()
对应于 MPI_Ireduce()
在非根等级上完成:这仅仅意味着发送缓冲区可以被覆盖。
我不清楚如何在 MPI 中正确使用非阻塞集合,特别是 MPI_Ireduce()
在这种情况下:
假设我想从根等级中收集一笔款项:
int local_cnt;
int total_cnt;
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
/* now I want to check if the reduce is finished */
if (rank == 0) {
int flag = 0;
MPI_Status status;
MPI_Test(&request, &flag, &status);
if (flag) {
/* reduce is finished? */
}
}
这是检查非阻塞 reduce 是否完成的正确方法吗?我的困惑来自两个方面:第一,根进程是否可以或应该使用 MPI_Test()
检查它,因为这只对根有意义?其次,由于 MPI_Test()
是本地操作,这个本地操作如何知道操作完成?它确实需要完成所有进程,对吧?
您必须检查所有参与等级是否完成,而不仅仅是根。
从用户的角度来看,您需要了解通信的完成情况,因为您不能对提供给非阻塞操作的内存做任何事情。 IE。如果你发送一个像 local_cnt
这样的局部作用域变量,你不能在确认操作完成之前写入它或离开它的作用域。
确保完成的一个选项是调用 MPI_Test
,直到它最终 returns flag==true
。仅当您可以在对 MPI_Test
:
{
int local_cnt;
int total_cnt;
// fill local_cnt on all ranks
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
int flag;
do {
// perform some useful computation
MPI_Status status;
MPI_Test(&request, &flag, &status);
} while (!flag)
}
如果您在两次调用之间无事可做,请不要循环调用 MPI_Test
。而是使用 MPI_Wait
,它会阻塞直到完成。
{
int local_cnt;
int total_cnt;
// fill local_cnt on all ranks
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);
// perform some useful computation
MPI_Status status;
MPI_Wait(&request, &status);
}
请记住,如果您根本没有有用的计算,并且由于死锁原因不需要非阻塞,请首先使用阻塞通信。如果您有多个正在进行的非阻塞通信,则有 MPI_Waitany
、MPI_Waitsome
、MPI_Waitall
及其测试变体。
Zulan 出色地回答了您问题的第一部分。
MPI_Reduce()
returns 当
- 可以在非根等级上覆盖发送缓冲区
- 结果在根等级上可用(这意味着所有等级都已完成)
所以非根等级无法知道根等级是否完成。如果你确实需要这些信息,那么你需要手动添加一个MPI_Barrier()
。也就是说,您通常 不需要 需要此信息,如果您认为您确实需要它,则您的应用可能有问题。
如果您使用非阻塞集合(例如 MPI_Wait()
对应于 MPI_Ireduce()
在非根等级上完成:这仅仅意味着发送缓冲区可以被覆盖。