OpenACC:如何将 openacc pragma 应用于“宏循环”

Posted

技术标签:

【中文标题】OpenACC:如何将 openacc pragma 应用于“宏循环”【英文标题】:OpenACC: How to apply openacc pragma to "macro loops" 【发布时间】:2021-09-23 06:11:19 【问题描述】:

我定义了这些宏:

#define I_LOOP(g, i)     _ibeg = g->lbeg[IDIR]; _iend = g->lend[IDIR];  \
                      for (i = _ibeg; i <= _iend; i++)
#define J_LOOP(g, j)     _jbeg = g->lbeg[JDIR]; _jend = g->lend[JDIR];  \
                      for (j = _jbeg; i <= _jend; j++)

我有这个循环我想并行化

  #pragma acc parallel loop collapse(2) 
  I_LOOP(g, i)
  J_LOOP(g, j)
    U0[j][i] = Uc[j][i];
  

但我收到错误:此处可能无法使用这种编译指示

有没有办法让这个循环与宏并行化?

【问题讨论】:

【参考方案1】:

首先,OpenACC loop 要求 for 循环在其中紧密嵌套,即没有前面的 _ibeg_iend 分配。

其次,对于这种#define 的用法,你也许可以用_Pragma 做点什么(见https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html 等):

#define I_LOOP(g, i)     _ibeg = g->lbeg[IDIR]; _iend = g->lend[IDIR];  \
                      _Pragma("acc parallel loop private(_jbeg, _jend") \
                      for (i = _ibeg; i <= _iend; i++)
#define J_LOOP(g, j)     _jbeg = g->lbeg[JDIR]; _jend = g->lend[JDIR];  \
                      _Pragma(acc loop) \
                      for (j = _jbeg; j <= _jend; j++)

(未经测试;您没有提供独立示例。)

(请注意,我还修正了i &lt;= _jend 错字。)

通过#define DO_PRAGMA(x) _Pragma(#x) 进行间接可能会很有用:

#define DO_PRAGMA(x) _Pragma(#x)

#define I_LOOP(g, i, pragma)     _ibeg = g->lbeg[IDIR]; _iend = g->lend[IDIR];  \
                      DO_PRAGMA(pragma) \
                      for (i = _ibeg; i <= _iend; i++)
#define J_LOOP(g, j, pragma)     _jbeg = g->lbeg[JDIR]; _jend = g->lend[JDIR];  \
                      DO_PRAGMA(pragma) \
                      for (j = _jbeg; j <= _jend; j++)

...,然后:

I_LOOP(g, i, "acc parallel loop private(_jbeg, _jend")
J_LOOP(g, j, "acc loop")
  U0[j][i] = Uc[j][i];

使用collapse 子句需要更多代码重组,这又要求for 循环紧密嵌套

【讨论】:

以上是关于OpenACC:如何将 openacc pragma 应用于“宏循环”的主要内容,如果未能解决你的问题,请参考以下文章

Openacc:如何使插入排序更加并行[关闭]

哪个 OpenACC 指令将告诉编译器仅在设备上执行语句?

MPI+OpenACC编程中的GPU间通信

如何在 Fortran 中将 OpenACC 与 cublasDgetrfBatched 接口?

在 OpenCL 上使用 OpenACC?

OpenAcc社区版安装教程(Linux版)