让第一个 proc 异步到达某个点
getting the first proc arriving at some point, asynchronously
我的程序从每个进程开始做一些工作,最后应该收集结果并计算最终结果。现在,每个人都将数据发送到 proc 0,它是执行最终计算任务的那个。我想找到一个在第一个完成其本地任务的进程上执行此操作。
有没有找到这个过程并异步告诉所有其他过程的技巧?我正在考虑使用异步集体操作,但找不到办法。
谢谢,
偷了
正如 Gilles 所说,您可以使用单向操作 (useful docs) 来设置一个变量,该变量将包含首先完成的进程的排名。您将变量设置为 -1,当一个进程完成时,它使用单边读取该变量(首先考虑阻止其他进程的访问以避免竞争)如果它是 -1,则进程将此变量设置为他的等级和成为 "master" 如果它是一个数字 >=0 那么进程成为(那个数字的)奴隶。
(正如 gilles 所指出的:对于版本 >3.0,可以使用 MPI_Compare_and_swap 执行一次 Get 和 Put(这可能比 Get 后跟 Put 更快))
只有在进程之间和少数进程之间的执行时间存在真正差异时,此方法才能正常工作。因此,在实施此类解决方案上浪费时间时应该小心。如果你有很大的负载不平衡(并且不能重新设计并行化以增加负载平衡),那将成功!
然后,如果您的目标是 >10 个进程,最好先将所有进程分组到嵌套子组网格上。然后在每个级别的组中执行技巧(避免有 100k 个进程试图读取相同的变量并浪费大量时间!)
这是一个简单的代码...
#include <mpi.h>
#include <thread>
#include <chrono>
#include <stdlib.h>
#include <iostream>
#include <time.h>
using namespace std;
int main(int argc, char** argv) {
MPI_Init(NULL, NULL);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
srand (time(NULL)+rank);
int wt = rand() % 5 + 1;
cout <<"rank: "<< rank<< " sleep: "<< wt<<endl;
//here is the magic...
int * flag;
MPI_Win window;
int master;
int compare = -1;
MPI_Win_allocate(sizeof(int), sizeof(int),MPI_INFO_NULL,
MPI_COMM_WORLD, &flag, &window );
*flag = -1;
this_thread::sleep_for(chrono::seconds(wt));
MPI_Win_lock (MPI_LOCK_EXCLUSIVE, 0, 0, window);
MPI_Compare_and_swap(&rank, &compare, &master, MPI_INT, 0,0, window);
MPI_Win_unlock (0, window);
if(master == -1)
{
cout<< "rank: "<<rank<<". I am the master"<<endl;
}
else
{
cout<< "rank: "<<rank<<". I am the slave of "<<master<<endl;
}
MPI_Win_free( &window );
MPI_Finalize();
}
输出:
mpirun --oversubscribe -np 4 ./test
rank: 2 sleep: 4
rank: 3 sleep: 1
rank: 0 sleep: 5
rank: 1 sleep: 2
rank: 3. I am the master
rank: 1. I am the slave of 3
rank: 2. I am the slave of 3
rank: 0. I am the slave of 3
mpirun --oversubscribe -np 4 ./test
rank: 0 sleep: 2
rank: 1 sleep: 4
rank: 2 sleep: 1
rank: 3 sleep: 3
rank: 2. I am the master
rank: 0. I am the slave of 2
rank: 3. I am the slave of 2
rank: 1. I am the slave of 2
我的程序从每个进程开始做一些工作,最后应该收集结果并计算最终结果。现在,每个人都将数据发送到 proc 0,它是执行最终计算任务的那个。我想找到一个在第一个完成其本地任务的进程上执行此操作。
有没有找到这个过程并异步告诉所有其他过程的技巧?我正在考虑使用异步集体操作,但找不到办法。
谢谢, 偷了
正如 Gilles 所说,您可以使用单向操作 (useful docs) 来设置一个变量,该变量将包含首先完成的进程的排名。您将变量设置为 -1,当一个进程完成时,它使用单边读取该变量(首先考虑阻止其他进程的访问以避免竞争)如果它是 -1,则进程将此变量设置为他的等级和成为 "master" 如果它是一个数字 >=0 那么进程成为(那个数字的)奴隶。
(正如 gilles 所指出的:对于版本 >3.0,可以使用 MPI_Compare_and_swap 执行一次 Get 和 Put(这可能比 Get 后跟 Put 更快))
只有在进程之间和少数进程之间的执行时间存在真正差异时,此方法才能正常工作。因此,在实施此类解决方案上浪费时间时应该小心。如果你有很大的负载不平衡(并且不能重新设计并行化以增加负载平衡),那将成功! 然后,如果您的目标是 >10 个进程,最好先将所有进程分组到嵌套子组网格上。然后在每个级别的组中执行技巧(避免有 100k 个进程试图读取相同的变量并浪费大量时间!)
这是一个简单的代码...
#include <mpi.h>
#include <thread>
#include <chrono>
#include <stdlib.h>
#include <iostream>
#include <time.h>
using namespace std;
int main(int argc, char** argv) {
MPI_Init(NULL, NULL);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
srand (time(NULL)+rank);
int wt = rand() % 5 + 1;
cout <<"rank: "<< rank<< " sleep: "<< wt<<endl;
//here is the magic...
int * flag;
MPI_Win window;
int master;
int compare = -1;
MPI_Win_allocate(sizeof(int), sizeof(int),MPI_INFO_NULL,
MPI_COMM_WORLD, &flag, &window );
*flag = -1;
this_thread::sleep_for(chrono::seconds(wt));
MPI_Win_lock (MPI_LOCK_EXCLUSIVE, 0, 0, window);
MPI_Compare_and_swap(&rank, &compare, &master, MPI_INT, 0,0, window);
MPI_Win_unlock (0, window);
if(master == -1)
{
cout<< "rank: "<<rank<<". I am the master"<<endl;
}
else
{
cout<< "rank: "<<rank<<". I am the slave of "<<master<<endl;
}
MPI_Win_free( &window );
MPI_Finalize();
}
输出:
mpirun --oversubscribe -np 4 ./test
rank: 2 sleep: 4
rank: 3 sleep: 1
rank: 0 sleep: 5
rank: 1 sleep: 2
rank: 3. I am the master
rank: 1. I am the slave of 3
rank: 2. I am the slave of 3
rank: 0. I am the slave of 3
mpirun --oversubscribe -np 4 ./test
rank: 0 sleep: 2
rank: 1 sleep: 4
rank: 2 sleep: 1
rank: 3 sleep: 3
rank: 2. I am the master
rank: 0. I am the slave of 2
rank: 3. I am the slave of 2
rank: 1. I am the slave of 2