使用 openMP 和 openACC 的多线程多 GPU 计算

Posted

技术标签:

【中文标题】使用 openMP 和 openACC 的多线程多 GPU 计算【英文标题】:Multi-threaded multi GPU computation using openMP and openACC 【发布时间】:2021-12-17 07:56:18 【问题描述】:

我正在尝试编写将 openmp 线程移植到单个 gpu 的代码。我发现的案例研究/代码非常少。因为我不是计算机科学背景。 我在编程方面的技能较少。

This is how the basic idea look's like

这是迄今为止开发的代码。

    CALL OMP_SET_NUM_THREADS(2)
!$omp parallel num_threads(acc_get_num_devices(acc_device_nvidia))
do while ( num.gt.iteration)

id = omp_get_thread_num()
call acc_set_device_num(id+1, acc_device_nvidia) 

    !!$acc kernels
    !error=0.0_rk
    !!$omp do
    !$acc kernels
    !!$omp do
    do j=2,nj-1
        !!$acc kernels  
        do i=2,ni-1
            T(i,j)=0.25*(T_o(i+1,j)+T_o(i-1,j)+ T_o(i,j+1)+T_o(i,j-1) )
        enddo
        !!$acc end kernels
    enddo
    !!$omp end do
    !$acc end kernels
    !!$acc update host(T,T_o)

    error=0.0_rk
    do j=2,nj-1
        do i=2,ni-1
            error = max( abs(T(i,j) - T_o(i,j)), error)
            T_o(i,j) = T(i,j)
        enddo
    enddo
    !!$acc end kernels
    !!$acc update host(T,T_o,error)
    
    iteration = iteration+1
    print*,iteration   , error 
    !print*,id
    
enddo
!$omp end parallel

【问题讨论】:

【参考方案1】:

这里有很多问题。

首先,您不能在 do while 上放置 OpenMP(或 OpenACC)并行循环。 while 是否有不确定的迭代次数,因此会创建一个依赖关系,即退出循环取决于循环的前一次迭代。您需要使用 DO 循环,其中迭代次数在进入循环时是已知的。

其次,即使将其转换为 DO 循环,如果并行运行,也会出现竞争条件。每个 OpenMP 线程都会将值分配给 T 和 T_o 数组的相同元素。加上 T_o 的结果被用作下一次迭代的输入,创建一个依赖。换句话说,如果你试图并行化外部迭代循环,你会得到错误的答案。

对于 OpenACC 代码,我建议在迭代循环周围添加一个数据区域,即 "!$acc data copy(T,T_o)" 在迭代循环之前和循环之后 "!$acc end data" ,以便数据仅在设备上创建一次。正如您现在所拥有的那样,每次通过迭代循环都会隐式创建和复制数据,从而导致不必要的数据移动。还在最大误差减少循环周围添加一个内核区域,以便将其卸载。

一般来说,我更喜欢使用 MPI+OpenCC 进行多 GPU 编程而不是 OpenMP。使用 MPI,域分解是固有的,然后您就有了 MPI 等级到设备的一对一映射。并不是说 OpenMP 不能工作,而是您通常需要手动分解域。此外,尝试管理多个设备内存并使它们保持同步可能会很棘手。加上 MPI,您的代码还可以跨节点而不是仅限于单个节点。

【讨论】:

是的,MPI+OpenACC 是一个不错的选择,但我们部门的其他人已经尝试过,即 MPI+OpenACC 与域分解,但在多个节点上的通信开销非常高。这就是为什么我尝试使用使用单节点和多 GPU 的 OpenMP+OpenACC 进行编码的原因。问题再次是我找不到任何相关代码,它利用 OpenMP+OpenACC 进行科学计算。

以上是关于使用 openMP 和 openACC 的多线程多 GPU 计算的主要内容,如果未能解决你的问题,请参考以下文章

openacc 与 openmp 和 mpi 的区别?

使用 openMP 进行多核处理与多线程

带继承的多线程 (C++)

极智Coding | OpenMP 多线程使用

NodeJS:具有多线程的本机 C++ 模块(openmp)

并行计算——OpenMP加速矩阵相乘