C++でSIMD命令を使用してuint32_t配列の値を比較し、この配列の新しい配列に値を戻したいと考えています。 それは多かれ少なかれ動作しますが、私はまだ4つのif節を使用して、値を書き戻すためのSIMD命令の後に値があるかどうかを判断しています。C++のSIMD命令を使用して値を比較して格納する
SIMD命令でこれを行う方法はありますか? 関数allocateAlignedBufferは、名前が示しているとおりに正しく動作しています。
uint32_t* testFunc(uint32_t* arr, uint32_t num, uint32_t* cnt) {
uint32_t numcnt = 4;
uint32_t * resArr = allocateAlignedBuffer<uint32_t>(num, true);
uint32_t * resPos = resArr;
*cnt = 0;
__m128i comp2 = _mm_set_epi32(10,10,10,10);
for (int i = 0; i < num; i+=4) {
__m128i positions = _mm_set_epi32(i+3,i+2,i+1,i);
__m128i vec = _mm_load_si128 (reinterpret_cast<const __m128i*> ((&arr[i])));
__m128i simdAnd2 = _mm_cmpge_ps(vec, comp2);
int comp = _mm_movemask_epi8 (simdAnd2);
if (comp == 0x0000) {
//std::cout << "nothing found\n";
continue;
}
else if (comp < 65535) {
if ( ((uint32_t *) &simdAnd2)[0]){
std::cout << "first byte not 0\n";
resPos[0] = ((uint32_t *) &positions)[0];
resPos++;
*cnt++;
}
if (((uint32_t *) &simdAnd2)[1]){
std::cout << "second byte not 0\n";
resPos[0] = ((uint32_t *) &positions)[1];
resPos++;
*cnt++;
}
if (((uint32_t *) &simdAnd2)[2]){
std::cout << "3rd byte not 0\n";
resPos[0] = ((uint32_t *) &positions)[2];
resPos++;
*cnt++;
}
if (((uint32_t *) &simdAnd2)[3]){
std::cout << "4th byte not 0\n";
resPos[0] = ((uint32_t *) &positions)[3];
resPos++;
*cnt++;
}
}
else { //all elements equal
resPos[0] = ((uint32_t *) &positions)[0];
resPos[1] = ((uint32_t *) &positions)[1];
resPos[2] = ((uint32_t *) &positions)[2];
resPos[3] = ((uint32_t *) &positions)[3];
resPos += numcnt;
*cnt += numcnt;
}
}
std::cout << "cnt "<<*cnt<<"\n";
return resArr;
}
また、おそらく私は信じるために多くの最適化があります。私は増加し、パフォーマンスをリードしなければならないいくつかの変更、行った
は印刷が必要ですか?コンパクションはpshufbトリックを使って行うことができますが、印刷する必要がある場合は問題ありません。 – harold
@haroldいいえ、私はちょうど私のために、私はそれをコメントした速度を評価しようとしたときに、私はそれをコピーしたときにそれを取ることを忘れていた – uv239