我正在尝试使用SSE加速我的方法(在Visual Studio上)。我是该地区的新手。我在我的方法中使用的主要数据类型是大小为32的位集,我主要使用的逻辑操作是AND操作(几乎不使用_BitScanForward)。我想知道是否可以使用SSE指令来加快我的程序。
这就是我现在正在做的事情(我已完成,无法直接比较结果):
我使用_mm_set_ps加载操作数(位集)。我在bitsets上使用to_ulong()将它们转换为无符号长整数:
__m128 v1 = _mm_set_ps(b1.to_ulong(),b2.to_ulong(),b3.to_ulong(),b4.to_ulong());
__m128 v2 = _mm_set1_ps(b.to_ulong())
接下来是实际的AND操作:
__m128 v3 = _mm_and_ps(v1,v2);
此时,我有两个问题:
我这样做的方式(使用to_ulong()将位集转换为无符号长整数)这是一个好方法吗?我怀疑有很大的开销可能会导致我使用SSE可能导致的性能提升。
将v3以4位集的形式存储在内存中的最佳方法是什么?我打算使用_mm_storeu_ps内在。
答案 0 :(得分:3)
有几件事:
如果您的位集基本上是32位整数,那么您应该使用合适的整数SIMD类型,即__m128i
,而不是浮点(__m128
)
_mm_set_XXX
宏相对昂贵 - 与常规SSE内在函数不同,它们可以生成相当多的指令 - 如果你所做的只是一个AND操作,那么_mm_and_XXX操作的任何性能优势都将超过擦除按_mm_set_XXX
操作
理想情况下,如果您只想在数组中使用AND一组位集,那么代码应如下所示:
const int N = 1024;
int32_t b1[N]; // 2 x arrays of input bit sets
int32_t b2[N];
int32_t b3[N]; // 1 x array of output bit sets
for (int i = 0; i < N; i += 4)
{
__m128i v1 = _mm_loadu_si128(&b1[i]); // load input bits sets
__m128i v2 = _mm_loadu_si128(&b2[i]);
__m128i v3 = _mm_and_si128(v1, v2); // do the bitwise AND
_mm_storeu_si128(&b3[i], v3); // store the result
}
如果您只想使用固定掩码就地使用AND数组,那么它将简化为:
const int N = 1024;
int32_t b1[N]; // input/output array of bit sets
const __m128i v2 = _mm_set1_epi32(0x12345678); // mask
for (int i = 0; i < N; i += 4)
{
__m128i v1 = _mm_loadu_si128(&b1[i]); // load input bits sets
__m128i v3 = _mm_and_si128(v1, v2); // do the bitwise AND
_mm_storeu_si128(&b1[i], v3); // store the result
}
注意:为了获得更好的性能,请确保输入/输出数组是16字节对齐的,然后使用_mm_load_si128
/ _mm_store_si128
而不是上面的未对齐对应数据。