我的问题是关于在基于内在函数的代码中定义 __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 上进行最大程度的优化编译。
最佳答案
选项 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);
// ...
}
}
关于c++ - 在哪里初始化 SSE 常量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19290343/