边界元法的 MPI 与 OPENMP 用法

计算科学 有限元 并行计算 mpi 边界元法
2021-11-30 07:03:09

我对 MPI 和 OPENMP 有一个实施问题。

我有一个大型的 3D 曲面网格,分为多个元素。我想遍历每个元素(外循环)并计算整个表面(内循环)的积分。总共有两个循环。我希望将此操作并行化。

这种操作发生在边界元方法中。例如,需要这样的操作来求解任意表面上的静电势。第一个循环遍历每个元素中心的每个评估点,第二个循环执行此特定的积分:x0x0

ϕ(x0)=SG(x0,x)[n(x)ϕ(x)]+ϕ(x)[n(x)G(x0,x)] dS

其中是拉普拉斯方程的自由空间格林函数,是我们想要在某些给定边界条件下求解的未知势。G(x0,x)=1/4π|x0x|ϕ

MPI:在这里我有两个选择。

  1. 我可以在一个处理器中生成网格并将其广播给所有其他处理器。然后我可以在处理器之间分配集成工作。假设我有 N_elm 元素和 n_procs 处理器,然后每个处理器负责集成 (N_elm/n_procs) 元素。(问题)虽然这在进行集成时不需要任何通信,但这是否会在内存中创建 n_procs 个网格副本?

  2. 我在一个处理器中生成网格,将其划分为 (N_elm/n_procs) 个元素,以便每个处理器只有域的一部分。每个处理器将能够在其自己的元素上循环并在其网格的一部分上进行本地集成。然而,为了集成网格的各个部分,它不需要通信。因此,我可以为此目的为每个大小为 [(N_elm/n_procs) 个元素 * 3] 的处理器创建一个临时数组。总的来说,每个处理器将创建 2*[(N_elm/n_procs) 个元素 * 3],一个用于自己的网格,另一个用于替换的临时网格。

(问题)是 1 还是 2 更可取,还是有第 3 个选项?

OPENMP:这里的实现更容易。 (问题)当我创建一个网格并并行化 for 循环时会发生什么?线程是给定整个网格的多个副本,类似于上面的数字 (1),还是线程之间共享网格,更像上面的数字 (2)。

1个回答

MPI Q1:在一个简单的实现中,是的,您最终会在每个进程上获得一个网格副本。您可以通过仅复制包含表面的网格部分来稍微减少这种情况,因为您只进行表面积分而不是体积积分。这在理论上将减少每个进程复制多少内存()。我想这个的伪代码可能看起来像这样:O(n2)O(n3)

on each process:
  allocate space for elements rank * nelems / nprocs to (rank + 1) * nelems / nprocs
  allocate space for the surface of the mesh
  initialize

  for each local element n:
    get x0_n
    for each face on the surface:
      compute the surface integral using x0_n

MPI Q2 : 如果你有足够的可用内存并且表面上没有太多的面,那么我认为方法 1 会更好,特别是如果你决定对我提出的方法 1 进行轻微修改。这种方法的进程间通信最少(基本上没有),通常边界面的数量远小于域中的元素数量。但是,这个数字可能仍然很大,并且不允许任何超出给定总表面积分粒度的并行化x0_n

您可以添加第二层并行化,其中表面积分本身被划分(例如通过 OpenMP 或 MPI 子通信器)并在给定单个值的情况下计算x0_n,然后执行与 MPI_Reduce 等效的操作以组合该表面积分的结果,尽管这实际上可能有帮助,也可能没有帮助。

如果您担心内存不足,那么您可以尝试使用诸如MPI_Win_allocate_shared或其他 MPI 窗口函数之类的东西来分配表面,尽管我认为这种方法会有一些通信开销(希望不会太多)。

OpenMP Q1:名义上没有。每个进程分配一次网格,并且该进程上的所有线程都可以共享内存访问网格。

请注意,需要注意的是 OpenMP 开始支持硬件加速器,因此在某些情况下,网格可能会在主内存和加速器的内存中复制。