std :: AVX内在函数数组

hel*_*922 5 c++ clang intrinsics avx

我不知道在理解AVX内在函数如何工作时是否缺少某些东西std::array,但是当我将两者合并时,我对Clang有一个奇怪的问题.

示例代码:

std::array<__m256, 1> gen_data()
{
    std::array<__m256, 1> res;
    res[0] = _mm256_set1_ps(1);
    return res;
}

void main()
{
    auto v = gen_data();
    float a[8];
    _mm256_storeu_ps(a, v[0]);
    for(size_t i = 0; i < 8; ++i)
    {
        std::cout << a[i] << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

Clang 3.5.0的输出(上面4个浮点数是垃圾数据):

1
1
1
1
8.82272e-39
0
5.88148e-39
0

GCC 4.8.2/4.9.1的产出(预期):

1
1
1
1
1
1
1
1

如果我不是传递v到gen_data作为输出参数它适用于两种编译器就好了.我愿意接受这可能是Clang中的一个错误,但是我不知道这可能是未定义的行为(UB).使用Clang 3.7*(svn build)和Clang进行测试现在似乎给出了我的预期结果.如果我切换到SSE 128位内在函数(__m128),那么所有编译器都会给出相同的预期结果.

所以我的问题是:

  1. 这里有UB吗?或者这只是Clang 3.5.0中的一个错误?
  2. 我的理解是__m256只是一个32字节对齐的内存块正确吗?还是有其他特别之处我必须要小心吗?

Sha*_*our 5

这看起来像是现在修复的clang bug,我们可以从这个bug报告中看到这个,它使用常规数组演示了一个非常类似的问题.

假设std::array实现其存储类似于:

T elems[N];
Run Code Online (Sandbox Code Playgroud)

这两者libc++并libstdc++似乎做那么这应该是类似的.其中一条评论说:

但是,libc ++ std::array<__m256i, 1>在任何优化级别都不起作用.

错误报告实际上是基于这个SO问题:这个错误的代码生成是否使用__m256数组的值来判断错误?这非常相似,但处理常规数组的情况.

错误报告包含一个可能的解决方案,OP声明就足够了:

在我的实际代码中,num_vectors是根据simd_pack类型的一些C++模板参数计算的.在许多情况下,这是1,但它通常也大于1.你的观察给了我一个想法; 我可以尝试引入一个模板专业化,捕捉案例num_vectors == 1.它可以只使用一个__m256成员而不是一个大小为1的数组.我将不得不检查它是否可行.

  • 你是对的。具体地说,这是长度为1的数组的问题,其中元素类型为AVX向量类型。报告它后,它很快就被修复了,我相信此修复程序已被包含在clang 3.6版本中。如果您不想使用中继,则可以尝试使用该版本。 (2认同)