1

我想并行化一个数值积分函数。我想在计算过程中使用这个函数。之前的工作应该在根进程中完成。这可以在 MPI 中完成吗?

 double integral_count_MPI(double (*function)(double) , double beginX, double endX, int      count)
 {
    double step, result;
    int i;
    if (endX - beginX <= 0) return 0;
    step = (endX - beginX) / count;
    result = 0;

    double *input = (double*)malloc((count+1) *sizeof(double));
    for (i = 0; i <= count; i ++)
    {
       input[i] = beginX + i*step;
    }
    // Calculate and gather
 }

编辑

算法:

  1 process calculation;
while:
  1 process calculation;
  integration very complex function with many processes;
  1 process calculation;
end while;
1 process calculation;
4

2 回答 2

3

MPI 提供了各种方法来构建在“幕后”使用它的库。对于初学者,您可以按需初始化 MPI。MPI-2 修改了调用的要求,MPI_Init因此每个兼容的实现都应该能够正确地使用NULL参数初始化MPI_Init(因为实际的程序参数可能对库不可用)。由于 MPI 应该只被初始化一次,所以库必须通过调用来检查它是否已经被初始化MPI_Initialized。代码基本上是这样的:

void library_init(void)
{
   int flag;

   MPI_Initialized(&flag);
   if (!inited)
   {
      MPI_Init(NULL, NULL);
      atexit(library_onexit);
   }
}

atexit()初始化代码还通过从 C 标准库调用来注册退出处理程序。在此退出处理程序中,如果 MPI 库尚未最终确定,它会最终确定它。如果不这样做,可能会导致mpiexec整个 MPI 作业终止,并显示至少一个进程已退出但未完成 MPI 的消息:

void library_onexit(void)
{
   int flag;

   MPI_Finalized(&flag);
   if (!flag)
      MPI_Finalize();
}

这种安排使您可以integral_count_MPI像这样编写函数:

double integral_count_MPI(...)
{
    library_init();

    ... MPI computations ...
}

integral_count_MPI将在第一次调用时要求初始化 MPI 库。library_init由于写入的方式,以后的调用不会导致重新初始化。也不需要明确的最终确定 - 退出处理程序会小心。

请注意,您仍然需要通过 MPI 进程启动器( 、 等)启动代码mpirunmpiexec并且必须小心执行 I/O,因为代码的串行部分将在每个实例中执行。许多支持 MPI 的库为此目的提供了自己的 I/O 例程,这些例程过滤进程等级并只允许等级 0 执行实际的 I/O。您还可以使用 MPI 的动态流程管理工具来按需生成其他流程,但这需要您将大部分流程管理抽象到执行集成的库中,这将使其变得非常复杂(以及代码你的主程序看起来很尴尬)。

于 2012-12-16T13:16:29.997 回答
2

你可以在这里找到 MPI 文档

基本上,逻辑如下:

int main()
{
    MPI_INIT(...);
    MPI_Comm_size(...);    //get the number of processes
    MPI_Comm_rank(...);    //get my rank

    if (rank == 0)     //master process
    {
        for (i = 1; i < n; i++)
            MPI_Send(...) //Send interval data specific to i process

        double result = 0;
        for (i = 1; i < n; i++)
        {
            double part_result;

            MPI_Recv(&part_result, ...) //Receive partial results from slaves

            result += part_result;
        }

        // Print result
    }
    else               //slave process
    {
        MPI_Recv(...)  //Receive interval data from master (rank 0 process)

        double result = integral_count_MPI(...);

        MPI_Send(...)  // Send results to master
    }

    MPI_FINALIZE(...);
}
于 2012-12-16T11:21:21.703 回答