私のプログラムで最も計算量の多い関数を最適化するための助けが必要です。現在、基本 (非 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
、パフォーマンスが向上するまで追加する目的はほとんどなく、この時点でコードが乱雑になるだけです。