OpenBLAS中的多线程线性系统解决方案

时间:2012-07-24 14:21:55

标签: multithreading fortran openmp lapack openblas

我有一个使用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

我需要做些什么才能使求解器并行化,因此每个内核都会计算求解器的部分内容?

1 个答案:

答案 0 :(得分:0)

在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的用法,我将向您展示一些应用程序的结果,该应用程序使用配置为使用OpenMP的FFTW(快速傅里叶变换实现)。执行是在16核双插槽Intel Xeon E5 @ 2.46GHz节点上执行的。

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

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

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

Unnested OpenMP version

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

Nested OpenMP version