在哪里初始化SSE常量

时间:2013-10-10 08:09:54

标签: c++ const sse simd

我的问题是在基于内在函数的代码中定义__m128 / __m128i编译时常量的最有效位置。

考虑两个选项:

选项A

__m128i Foo::DoMasking(const __m128i value) const
{
    //defined in method
    const __m128i mask = _mm_set1_epi32(0x00FF0000);
    return _mm_and_si128(value, mask);
}

选项B

//Foo.h
const __m128i mask = _mm_set1_epi32(0x00FF0000);

//Foo.cpp
__m128i Foo::DoMasking(const __m128i value) const
{
    return _mm_and_si128(value, mask);
}
  • 选项A是否会产生性能损失,还是会优化到选项B的等效值?
  • 是否有更好的选项C
  • 答案的变化取决于方法是否内联?
  • _mm_set1_epi32 / __mm_set_epi32是加载常量的最佳方法吗?我已经看到了一些问题,其中int[4]已生成并投射到__m128i

我知道所有这些问题的适当答案是“检查反汇编!”,但我在生成和解释它方面都缺乏经验。

我正在MSVC上进行最大程度的优化编译。

1 个答案:

答案 0 :(得分:2)

选项A 可能可以正常 - 编译器应该在内联此函数时做正确的事情并且它应该将掩码常量提升到任何循环之外,但是在我的经验中,最安全的选择,特别是如果你希望它在多个平台/编译器中可靠地工作,就是将它重新分解为一种稍微不那么优雅但可能更有效的形式:

__m128i Foo::DoMasking(const __m128i value, const __m128i mask) const
{
    return _mm_and_si128(value, mask);
}

void Foo::DoLotsOfMasking(...)
{
    const __m128i mask = _mm_set1_epi32(0x00FF0000);

    for (int i = 0; ...; ...)
    {
        // ...
        v[i] = DoMasking(x[i], mask);
        // ...
    }
}