如何访问和打印在MPI工作人员中分发的完整向量?

如何从MPI中的单个线程访问全局向量?

我正在使用一个库 – 特别是一个ODE求解器库 – 名为CVODE(SUNDIALS的一部分)。 该库与MPI一起使用,因此多个线程并行运行。 它们都运行相同的代码。 每个线程将一个数据“旁边”发送给它。 但我希望其中一个线程(rank = 0)在某些点打印出数据的状态。

该库包含函数,以便每个线程可以访问自己的数据( 本地向量 )。 但是没有方法可以访问全局向量。

我需要在特定时间输出所有方程的值。 为此,我需要访问全局向量。 任何人都知道如何获取MPI向量中的所有数据(如果可能,使用CVODE)?

例如,这是我的代码,每个线程运行

for (iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) { flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL); if(check_flag(&flag, "CVode", 1, my_pe)) break; if (my_pe == 0) PrintData(t, u); } ... static void PrintData(realtype t, N_Vector u) { I want to print data from all threads in here } 

在函数f (我正在解决的函数)中,我使用MPI_SendMPI_Recv来回传递数据。 但我不能在PrintData中真正做到这一点,因为其他进程已经运行。 另外,我不想添加消息传递开销。 我想访问PrintData的全局向量,然后打印出所需的内容。 可能吗?

编辑 :在等待更好的答案时,我编写了每个线程将数据传递回第0个线程。 我不认为这会增加太多的消息传递开销,但我仍然希望听到专家知道是否有更好的方法(我确定没有更糟糕的方法!:D)。

编辑2 :尽管angainor的解决方案肯定更优越,但我坚持使用我创造的解决方案。 对于具有相同问题的任何人的未来参考,以下是我如何做到的基础知识:

 /* Is called by all threads */ static void PrintData(realtype t, N_Vector u, UserData data) { ... declarations and such ... for (n=1; n<=my_length; n++) { mass_num = my_base + n; z[mass_num - 1] = udata[n-1]; z[mass_num - 1 + N] = udata[n - 1 + my_length]; } if (my_pe != 0) { MPI_Send(&z, 2*N, PVEC_REAL_MPI_TYPE, 0, my_pe, comm); } else { for (i=1; i<npes; i++) { MPI_Recv(&z1, 2*N, PVEC_REAL_MPI_TYPE, i, i, comm, &status); for (n=0; n<2*N; n++) z[n] = z[n] + z1[n]; } ... now I can print it out however I like... return; } 

使用MPI时,各个线程无法访问“全局”向量。 它们不是线程,它们是可以在不同物理计算机上运行的进程,因此无法直接访问全局数据

要做你想做的事,你可以将矢量发送到其中一个MPI进程(你这样做)并在那里打印,或者按顺序打印本地工人部分。 使用这样的函数:

 void MPI_write_ivector(int thrid, int nthr, int vec_dim, int *v) { int i, j; int curthr = 0; MPI_Barrier(MPI_COMM_WORLD); while(curthr!=nthr){ if(curthr==thrid){ printf("thread %i writing\n", thrid); for(i=0; i 

所有MPI进程都应该同时调用它,因为内部存在屏障和广播。 本质上,该过程确保所有MPI进程按顺序打印其向量部分,从等级0开始。由于在任何给定时间只有一个进程写入,因此数据不会混乱。

在上面的示例中,使用了Broadcast,因为它为线程打印结果的顺序提供了更大的灵活性 - 当前输出的线程可以决定,接下来是谁。 您也可以跳过广播并仅使用屏障

 void MPI_write_ivector(int thrid, int nthr, int vec_dim, int *v) { int i, j; int curthr = 0; while(curthr!=nthr){ if(curthr==thrid){ printf("thread %i writing\n", thrid); for(i=0; i