【问题标题】:Existence of "simd reduction(:)" In GCC and MSVC?GCC 和 MSVC 中是否存在“simd reduction(:)”?
【发布时间】:2013-07-10 06:01:27
【问题描述】:

simd pragma 可以与 icc 编译器一起使用来执行归约运算符:

#pragma simd
#pragma simd reduction(+:acc)
#pragma ivdep
for(int i( 0 ); i < N; ++i )
{
  acc += x[i];
}

在 msvc 或/和 gcc 中是否有任何等效的解决方案?

参考(p28):http://d3f8ykwhia686p.cloudfront.net/1live/intel/CompilerAutovectorizationGuide.pdf

【问题讨论】:

    标签: visual-c++ gcc vectorization simd icc


    【解决方案1】:

    gcc 需要 -ffast-math 来启用此优化(如上面给出的参考中所述),无论使用#pragma omp simd reduction。 icc 对这种优化的 pragma 的依赖性越来越低(除了 /fp:fast 在没有 pragma 的情况下需要),但原始帖子中额外的 ivdep 和 simd pragma 是不可取的。当给出不包括所有相关归约、firstprivate 和 lastprivate 子句的 pragma simd 时,icc 可能会做坏事(并且 gcc 可能会与 -ffast-math 中断,特别是与 -march 或 -mavx 结合使用)。 msvc 2012/2013 在自动矢量化方面非常有限。没有 simd 缩减,OpenMP 并行区域内没有向量化,没有条件向量化,并且没有利用 __restrict 在向量化中的优势(有一些运行时检查可以降低效率,但在没有 __restrict 的情况下安全地进行向量化)。

    【讨论】:

    • 组合 gcc -fopenmp -march=native -funsafe-math-optimizations -O3 对我来说失败了。如果我删除这 3 个选项中的任何一个或减少到 -march=corei7 或 -O2,则案例成功。 -march=native 对 avx 和 avx2 架构更具侵略性,因此它的影响可能并不完全令人惊讶。
    • 我认为某处记录了 -O3 -ffast-math 是其中一些优化所必需的,因此 -ffast-math 对 -O2 的风险不大也就不足为奇了。
    • 在发布到github.com/tprince/lcd 的基准测试中,我将 C 源文件分为需要 -ffast-math 和需要 -fopenmp 的文件。对于各种英特尔编译器,我对每种源语言都使用相同的选项。
    • -fopenmp 和 -ffast-math 之间的冲突问题也出现在 g++ 中,在 Westmere 平台上,类似地解决了。 C++ 版本也为 MSVC 设置。
    【解决方案2】:

    对于 Visual Studio 2012: 带选项/O1 /O2/GL,报告矢量化使用/Qvec-report:(1/2)

    int s = 0; 
    for ( int i = 0; i < 1000; ++i ) 
    { 
    s += A[i]; // vectorizable 
    }
    

    在减少“float”或“double”类型的情况下,矢量化要求抛出/fp:fast 开关。这是因为矢量化归约操作取决于“浮点重新关联”。仅当抛出 /fp:fast 时才允许重新关联

    参考(相关文档;p12)http://blogs.msdn.com/b/nativeconcurrency/archive/2012/07/10/auto-vectorizer-in-visual-studio-11-cookbook.aspx

    【讨论】:

      【解决方案3】:

      GCC 绝对可以矢量化。假设你有包含内容的文件 reduc.c:

      int foo(int *x, int N)
        {
          int acc, i;
      
          for( i = 0; i < N; ++i )
            {
              acc += x[i];
            }
      
          return acc;
        }
      

      用命令行编译它(我使用 gcc 4.7.2):

      $ gcc -O3 -S reduc.c -ftree-vectorize -msse2
      

      现在你可以在汇编器中看到向量化循环了。

      你也可以打开详细的矢量化输出,比如

      $ gcc -O3 -S reduc.c -ftree-vectorize -msse2 -ftree-vectorizer-verbose=1
      

      现在您将获得控制台报告:

      Analyzing loop at reduc.c:5
      Vectorizing loop at reduc.c:5
      5: LOOP VECTORIZED.
      reduc.c:1: note: vectorized 1 loops in function.
      

      Look at the official docs 更好地理解 GCC 可以和不能向量化的情况。

      【讨论】:

      • 抱歉,我错过了这个:“要启用浮点归约的矢量化,请使用 -ffast-math 或 -fassociative-math。”
      猜你喜欢
      • 1970-01-01
      • 2011-08-22
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 2021-03-09
      • 2020-08-13
      • 2021-08-12
      相关资源
      最近更新 更多