我需要一些帮助来优化我的程序中计算量最大的功能。目前,我发现基本(非 SSE)版本明显更快(高达 3 倍)。因此,我请求您帮助纠正这个问题。
该函数在无符号整数向量中查找子集,并报告它们是否存在。为了您的方便,我只包含了相关的代码片段。
首先是基本变体。它检查是否blocks_
是x.blocks_
. (不完全相等。)这些是位图,也就是位向量或位集。
//Check for self comparison
if (this == &x)
return false;
//A subset is equal to or smaller.
if (no_bits_ > x.no_bits_)
return false;
int i;
bool equal = false;
//Pointers should not change.
const unsigned int *tptr = blocks_;
const unsigned int *xptr = x.blocks_;
for (i = 0; i < no_blocks_; i++, tptr++, xptr++) {
if ((*tptr & *xptr) != *tptr)
return false;
if (*tptr != *xptr)
equal = true;
}
return equal;
然后是 SSE 变体,可惜它没有按照我的预期执行。这两个片段都应该寻找相同的东西。
//starting pointers.
const __m128i* start = (__m128i*)&blocks_;
const __m128i* xstart = (__m128i*)&x.blocks_;
__m128i block;
__m128i xblock;
//Unsigned ints are 32 bits, meaning 4 can fit in a register.
for (i = 0; i < no_blocks_; i+=4) {
block = _mm_load_si128(start + i);
xblock = _mm_load_si128(xstart + i);
//Equivalent to (block & xblock) != block
if (_mm_movemask_epi8(_mm_cmpeq_epi32(_mm_and_si128(block, xblock), block)) != 0xffff)
return false;
//Equivalent to block != xblock
if (_mm_movemask_epi8(_mm_cmpeq_epi32(block, xblock)) != 0xffff)
equal = true;
}
return equal;
您对我如何改进 SSE 版本的性能有什么建议吗?难道我做错了什么?或者这是应该在其他地方进行优化的情况?
我还没有在剩余的计算中添加no_blocks_ % 4 != 0
,但是在性能提高之前这样做几乎没有什么目的,而且此时只会弄乱代码。