MPI策略-并行化成一个函数- MPI_Gather

MPI Strategy - parallelization into a function - MPI_Gather

本文关键字:MPI 一个 函数 Gather 策略 并行化      更新时间:2023-10-16

我尝试用MPI并行化代码。在这段代码中,要并行化的部分位于一个函数中。我必须将顺序循环转换为MPI并行循环。

在这个MPI循环之后,我必须得到一个全局数组,我打算使用MPI_Gather来获得这个数组。

下面是代码的结构:
int main() {
    double *array_global;
    data1 = read(file1);
    data2 = read(file2);
    data3 = compute_on_data(data1, data2);
    write(file3,data3);
    function_to_parallelize(data1, data2, data3, array_global);
}

和函数" function_to_parallelize ":

function_to_parallelize(data1, data2, data3, array_global) {
  int i;
  for (i = 0;i<size_loop; i++)
     {
       compute(data1, data2, data3, i, array_global);
     }
   write(file4, array_global);
}

我的第一个问题是:我可以通过在main(添加rank_mpinb_process参数)中执行MPI并行化操作吗?

int main() {
int rank_mpi, nb_process;
MPI_Init(&argc, &argv); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank_mpi); 
MPI_Comm_size(MPI_COMM_WORLD, &nb_process);
    double *array_global;
    data1 = read(file1);
    data2 = read(file2);
    data3 = compute_on_data(data1, data2);
    if (rank_mpi = 0) {
      write(file3,data3);}
    function_to_parallelize(data1, data2, data3, *array_global, rank_mpi, nb_process);
}

在" function_parallelize "

function_to_parallelize(data1, data2, data3, array_global, rank_mpi, nb_process) {
  int i;
  double *gathered_array_global;
  int size_block = size_loop/nb_process;
  for (i = rank_mpi*size_block; i < (rank_mpi+1)*size_block; i++)
     {
       compute(data1, data2, data3, i, array_global);
     }
   MPI_Gather(gathered_array_global, array_global, 0); // Gather all array_global into gathered_array_global for root process "rank_mpi = 0"
   if (rank_mpi = 0) {
     write(file4, gathered_array_global);}
}

? ?我的意思是,如果我使用MPI_Gather函数,我可以有理想的结果,即所有的array_global都放入我想在"file4"中写入的最终数组中吗?

我只知道,传统上,MPI_Gather用于main()中收集所有子数组。如果我进入一个例程,我认为进程不能与其他进程同步,因此它们之间不能通信,对吗?

我的第二个问题是关于这种并行化所采用的策略:你认为所有进程都可以读取"file1","file2"而不会发生冲突吗?

对于写"data3",我认为我只能写一个进程(rank_mpi = 0),否则,在执行时会出现错误

感谢您的帮助和建议

如果用正确的语法编写,您的伪代码将运行。在main以外的函数中使用MPI调用没有任何问题。但我不认为它会达到你想要的效果。在function_to_parallelize中使用MPI调用很好,但让我们仔细看看,

function_to_parallelize(data1, data2, data3, array_global, rank_mpi, nb_process) {
  int i;
  double *gathered_array_global;
  int size_block = size_loop/nb_process;
  for (i = rank_mpi*size_block; i < (rank_mpi+1)*size_block; i++)
     {
       compute(data1, data2, data3, i, array_global);
     }
   MPI_Gather(gathered_array_global, array_global, 0); // Gather all array_global into gathered_array_global for root process "rank_mpi = 0"
   if (rank_mpi = 0) {
     write(file4, gathered_array_global);}
}

您将问题分解为每个进程上每个array_global的一部分将被计算。例如,假设rank_mpi0-3size_loop=40,那么size_block=10。这意味着array_global[0-9]将在进程0上计算,array_global[10-19]将在进程1上计算,以此类推。然后,当您调用MPI_Gather时,您将需要gathered_array_global的大小为nb_process * size_loop来保存数据。

我认为你想要的是使更小的局部数组,只是适合计算的数据(换句话说,大小为10的数组),然后将它们传递给MPI_Gather收集到大小为40的数组(gathered_array_global)。当然,您还必须小心,以防数组的大小不能被您正在使用的进程数整除。

让所有进程同时读取文件在理论上是可以的,但是你可以很容易地通过要求大量的同时读取来破坏几乎任何文件系统。我会用广播,但这取决于你的具体情况。

最后,除非使用并行输出库,否则不能让多个进程同时写入文件。无论您使用的是什么文件系统,这都有可能造成破坏。最好做你想做的,然后从一个进程中收集和编写。