我的程序从每个进程开始做一些工作开始,最后应该收集结果并计算最终结果。现在,每个人都将数据发送到proc 0,它是执行最终计算任务的人。我想找到一个在完成本地任务的第一个过程中执行此操作。
找到这个过程并异步告知所有其他过程是否有技巧?我当时在考虑使用异步集体操作,但是找不到一种方法。
谢谢, 偷
答案 0 :(得分:1)
正如Gilles所说,您可以使用单面操作(useful docs)来设置一个变量,该变量将包含首先完成的进程的等级。您将变量设置为-1,当一个进程完成时,它使用一侧读取该变量(首先考虑阻止其他进程访问以避免种族),如果它为-1,则该进程将其设置为他的等级,如果它是一个数字> = 0,则成为“主”,然后该进程成为(该数字的)从属。
(正如吉尔斯指出的那样:在版本> 3.0中,可以使用MPI_Compare_and_swap一次执行“获取和放置”操作(这可能比“获取”之后放置“放置”要快))
仅当您在进程之间的执行时间和少量进程之间存在真正的差异时,此方法才能正常工作。因此,在浪费时间实施这种解决方案时应该小心。如果您有很大的负载不平衡(并且不能重新设计并行化以增加负载平衡),那就可以了! 然后,如果您的目标是> 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