【问题标题】:std::array of AVX intrinsicsAVX 内部函数的 std::array
【发布时间】:2015-05-27 06:52:57
【问题描述】:

我不知道我对 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;
    }
}

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 字节对齐的内存块的理解是否正确?还是有什么特别之处需要我小心处理?

【问题讨论】:

    标签: c++ clang intrinsics avx


    【解决方案1】:

    这看起来像是现在已修复的 clang 错误,我们可以从 bug report 中看到这一点,它演示了使用常规数组时非常相似的问题。

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

    T elems[N];
    

    libc++libstdc++ 似乎都这样做了,那么这应该是类似的。其中一位 cmets 说:

    但是,libc++ 的 std::array&lt;__m256i, 1&gt; 在任何优化级别都不起作用。

    错误报告实际上是基于这个 SO 问题:Is this incorrect code generation with arrays of __m256 values a clang bug?,它非常相似,但处理的是常规数组情况。

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

    在我的实际代码中,num_vectors 是根据 simd_pack 类型的一些 C++ 模板参数计算得出的。在许多情况下,结果是 1,但它也经常大于 1。不过,您的观察给了我一个想法;我可以尝试引入一个模板专业化来捕获num_vectors == 1 的情况。它可以只使用单个 __m256 成员而不是大小为 1 的数组。我必须检查一下它是否可行。

    【讨论】:

    • 你是对的。具体来说,这是长度为 1 的数组的问题,其中元素类型是 AVX 向量类型。它在被报告后很快得到修复,我相信这个修复被合并到了 clang 3.6 版本中。如果你不想使用主干,你可以试试那个版本。
    • @JasonR 哦,你知道这实际上是在错误报告中,我错过了,让我更新我的答案。做得好的问题也 +1。
    • 作为一个合适的解决方法(在错误报告中建议),我创建了一个简约的 std::array 替换,它专门用于统一大小的数组以包含单个元素而不是大小为 1 的数组。
    • @helloworld922 我错过了这个建议,我应该看到的,我会添加它。
    猜你喜欢
    • 2015-01-02
    • 2014-07-12
    • 1970-01-01
    • 2013-12-25
    • 2016-05-31
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多