让第一个 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