【问题标题】:Can c++ loops be guaranteed by the compiler (gcc)?编译器(gcc)可以保证 c++ 循环吗?
【发布时间】:2016-03-03 08:54:00
【问题描述】:

我必须进行以下 AVX 操作:

__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3,2,1,0));
func = _mm256_load_ps(fPtr+0);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(2,3,0,1));
func = _mm256_load_ps(fPtr+1);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(1,0,3,2));
func = _mm256_load_ps(fPtr+2);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(0,1,2,3));
func = _mm256_load_ps(fPtr+3);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

可以这样改写:

__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
for(int i=0;i<4;++i)
{
    perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3^i,2^i,1^i,0^i));
    func = _mm256_load_ps(fPtr+i);
    acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
}

这在 gcc 4.9.1 中编译,尽管 _mm256_shuffle_ps 只接受立即整数值作为第三个参数。这意味着,i 被接受为立即数,因此意味着循环已展开。

所以我很好奇:这是编译器保证的,还是当优化标志被修改或 gcc 版本改变时会导致编译错误?使用其他编译器怎么样(msvc、icc、clang...)

【问题讨论】:

  • 你试过-O0吗?会发生什么?
  • 另外,您如何得出只支持立即数的结论? GCC implementation 似乎采用了const int,而the Intel spec 似乎表示相同。
  • const int 签名没有说明任何内容,因为语言中没有任何内容指定参数是否为立即数。此外,英特尔内部文档中的任何 imm 参数都意味着立即数。这在 MSDN 文档中更清楚。最后,在 gcc 中使用非立即数会触发错误:“最后一个参数必须是 8 位立即数”

标签: c++ loop-unrolling


【解决方案1】:

内在函数确实需要立即值。编译之所以有效,是因为它通过展开循环被优化为常量,并且使用 -O0 编译确实会触发以下错误:

(...)\lib\gcc\x86_64-w64-mingw32\4.9.2\include\avxintrin.h:331: 错误:最后一个参数必须是 8 位立即数

      __mask);
            ^

这里用icc报告了一个类似的案例:

https://software.intel.com/en-us/forums/intel-c-compiler/topic/287217

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 2017-11-05
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多