【问题标题】:Multi-threaded linear system solution in OpenBLASOpenBLAS 中的多线程线性系统解决方案
【发布时间】:2012-07-24 14:21:55
【问题描述】:

我有一个使用 Fortran 95 和 gfortran 编译器的代码。我也在使用 OpenMP,我必须处理非常大的数组。在我的代码中,我还必须使用 OpenBLAS 的求解器 DGTSV 求解线性方程组。我想并行化这个求解器以及使用应该能够做到的openblas。但我在语法上有问题。使用附加的伪代码,所有 4 个 CPU 几乎 100% 使用,但我不确定每个内核是否单独求解线性方程,或者它们是否将其拆分为多个部分并并行计算。 整个东西都是使用gfortran -fopenmp -lblas a.f95 -o a.out编译的

所以我的伪代码看起来像

program a
implicit none
integer, parameter  ::  N   =       200
real*8, dimension(numx) ::  D   =       0.0
real*8, dimension(numx-1):: DL  =       0.0
real*8, dimension(numx-1):: DU  =       0.0
real*8, dimension(numx) ::  b   =       0.0
integer         ::  info    =       0
integer :: numthread=4
...
!$OMP PARALLEL NUM_THREADS(numthread)
...
!$OMP DO
...
!$OMP END DO
CALL DGTSV(N,1,DL,D,DU,b,N,info)
!$OMP DO
...
!$OMP END DO
...
!$OMP END PARALLEL
end program a

我必须做些什么才能使求解器并行化,以便每个内核计算求解器的各个部分?

【问题讨论】:

  • 每个线程都会求解整个线性方程组,重复所有其他线程的工作,即使 OpenBLAS 是在 OpenMP 支持下编译的。您需要在并行区域外调用DGTSV,它将在子程序实现内部创建自己的并行区域。
  • 酷,感谢您的快速回复。我会这样尝试。
  • 您还可以将对 DGTSV 的调用放入 OpenMP SINGLE 构造中并启用嵌套并行。这将为您节省一小部分时间。
  • 好的,谢谢!我知道这个选项。我会知道节省了多少时间。

标签: multithreading fortran openmp lapack openblas


【解决方案1】:

在 OpenMP 并行区域内,所有线程都执行相同的代码(与 MPI 中一样),并且仅当线程到达循环/部分/任务时才拆分工作。

在您的示例中,循环 (OMP DO) 内的工作分布在可用线程之间。循环完成后,隐式屏障同步所有线程,然后它们并行执行函数DGTSV。子程序返回后,循环再次拆分。

@HristoIliev 建议使用OMP SINGLE 子句。这限制了内部的一段代码只能由一个线程执行,并强制所有其他线程等待它(除非你指定nowait)。

另一方面,嵌套并行被称为在另一个并行区域内声明一个并行区域的情况。当您在并行区域内执行对 OpenMP 并行化库的调用时,这也适用。

默认情况下,OpenMP 不会增加嵌套并行区域的并行度,而是只有进入并行区域的线程才能执行它。可以使用环境变量 OMP_NESTED 将这种行为更改为 true

OMP SINGLE 解决方案比将并行区域一分为二要好得多,因为资源会在下一个循环中重复使用:

$!OMP PARALLEL
  $!OMP DO
  DO ...
  END DO

  $!OMP SINGLE
  CALL DGTSV(...)

  $!OMP DO
  DO ...
  END DO
$!OMP END PARALLEL

为了说明OMP_NESTED 的用法,我将向您展示我从一个使用 FFTW(一种快速傅立叶变换实现)配置为使用 OpenMP 的应用程序中得到的一些结果。执行是在 16 核双路 Intel Xeon E5 @2.46GHz 节点中执行的。

下图显示了整个应用程序花费的时间,其中并行区域在 CPU > 1 时出现,在 CPU = 1 时出现序列化区域,在 CPU = 0 时出现同步区域。

应用程序是令人尴尬的并行,因此在这种特殊情况下使用嵌套是不值得的(FFTW 不能很好地扩展)。

这是OMP_NESTED=false 执行。观察并行量如何受到外部并行区域 (ftdock) 中所用线程数量的限制。

这是OMP_NESTED=true 执行。在这种情况下,可以进一步增加并行度,而不是在外部并行区域上花费的线程数量。在这种情况下,可能的最大并行度为 16,当 8 个外部线程创建一个对等点来执行内部并行区域时,或者它们是 4 个,每个线程创建 3 个额外线程 (8x2 = 4x4 = 16)。

【讨论】:

  • 结论是什么?也许只有我一个人,但我不知道如何解释该图表。问题本身(与 FFTW)对我来说非常重要。
  • 结论是:这取决于,通常情况下。该图显示了程序可以并行运行的线程数(最好是单条超过 16,这是最大核心数)。在我的特定示例中,最好的策略是将 16 个线程扔到外部并行区域并使用库的序列化版本。在 OP 的情况下,如果 BLAS 例程必须被序列化,那么使用嵌套并行是一个很好的起点,尽管所有这些同步障碍都会在某些时候限制可伸缩性。
猜你喜欢
  • 2013-04-18
  • 2016-01-30
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多