【问题标题】:Standalone loop collapsing in OpenMPOpenMP 中的独立循环崩溃
【发布时间】:2021-12-20 05:31:24
【问题描述】:

我有一个嵌套循环,如下所示 -

for(int i=0; i<limit1; i++)
{
    for(int j=0; j<limit2; j++){
       /*
          Code with Custom function calls, branching etc etc.

      */
  }
}

内循环和外循环迭代是相互独立的。由于这个循环不能简单地向量化,我想将它折叠到一个巨大的迭代空间中,以便可以更有效地展开它,从某种意义上说,不是只展开内部循环,而是可以展开组合的迭代空间。

我不想并行化它。根据我的理解,我不认为 openmp 提供了像 #pragma omp collapse(2) 这样的独立的 collapsing pragma,而是将 collapse 子句与 simdfor 等其他 pragma 结合使用。

可以通过 OpenMP 或其他方法来实现。

PS - 我不确定这种方法的优缺点,是否会显着提高性能等等。如果有人从理论上解释(或者如果可以的话)如何(即在基准测试之前) ) 确定这一点,那就太好了。

TIA

【问题讨论】:

  • 为什么不手动折叠循环? for( n=0; n&lt;limit1*limit2;n++){ i=n/limit1; j=n%limit1; ......}我不认为它会明显更快,但你可以尝试....

标签: c++ openmp vectorization loop-unrolling


【解决方案1】:

首先,OpenMP 是“一种并行编程模型,可在不同供应商的架构之间移植”(来源:OpenMP 5.1 specification)。因此,如果您不想并行化循环,那么它可能不是正确的工具。

但是,请注意 OpenMP 提供指令 unroll 来完全或部分展开循环嵌套的最外层循环。完全展开循环的full 子句要求迭代计数(例如limit1)是一个编译时常量(否则理论上是不可能的)。 partial 子句可以用一个整数参数化,以控制展开多少次迭代。到目前为止,GCC、ICC 和 Clang 都不支持这两个子句。

还有tile 指令可以重新排序两个嵌套循环的迭代,以便获得2D 固定大小的图块。它没有向编译器指定应该展开循环。然而,一个积极优化的编译器可能会展开固定大小的循环嵌套,如果它不包含许多分支或函数调用(因为它通常不利于性能)。该指令不能unroll 一起使用(因为瓦片循环没有规范的循环嵌套形式)。

请注意,如果迭代计数不是编译时常量,则折叠(手动或使用工具自动)两个嵌套循环肯定不会帮助编译器,并且通常不会在limit2不是二的幂。实际上,在这种情况下,肯定需要通过变量使用慢速模数或相当慢的无分支条件移动。展开这样的循环对于编译器来说是非常困难的(如果可能的话)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多