2017-02-21 16 views
4

私は、SIMDを使用してコードのこの部分を書き換えるしようとしている:SIMDを使用して、8ビットマスクを16ビットマスクに拡張するにはどうすればよいですか?

int16_t v; 
int32_t a[16]; 
int8_t b[32]; 
... 
((int16_t *)a[i])[0] = b[i]==1? -v:v; 
((int16_t *)a[i])[1] = b[i]==1? -v:v; 

私は価値が選んを実行するために_mm256_and_si256_mm256_andnot_si256を使用することができた後、マスクベクトルを生成する_mm256_cmpeq_epi8を使用して考えていました。
問題はb [i]は8ビット整数で、vは16ビットです。
マスクベクトルが{0xff, 0x00, 0xff, 0x00...}の場合、16ビット値を選択するには{0xffff, 0x0000, 0xffff, 0x0000...}に拡張する必要があります。
どうすればいいですか? は(私の英語のため申し訳ありませんが)

編集:
私はthis questionからのインスピレーションと解決策を見つけました。
_mm256_shuffle_epi256は、128ビットのレーン内でしか実行できません。 したがって、_mm256iマスクを2つの_mm128iレジスタに分割しました。そして、_mm256_broadcastsi128_si256_mm256_shuffle_epi256で結果を得ました。

答えて

2

ソリューションがあります:

int16_t v; 
int32_t a[16]; 
int8_t b[32]; 

//((int16_t *)a[i])[0] = b[i]==1? -v:v; 
//((int16_t *)a[i])[1] = b[i]==1? -v:v; 

__m256i _1 = _mm256_set1_epi8(1); 
__m256i _b = _mm256_loadu_si256((__m256i*)b); 

__m256i mask8i = _mm256_cmpeq_epi8(_b, _1); // 8-bit compare mask 

__m256i permutedMask8i = _mm256_permute4x64_epi64(mask8i, 0xD8); 
__m256i mask16iLo = _mm256_unpacklo_epi8(permutedMask8i, permutedMask8i); // low part of 16-bit compare mask 
__m256i mask16iHi = _mm256_unpackhi_epi8(permutedMask8i, permutedMask8i); // high part of 16-bit compare mask 

__m256i positiveV = _mm256_set1_epi16(-v); //positive mask condition 
__m256i negativeV = _mm256_set1_epi16(v); //negative mask condition 

__m256i _aLo = _mm256_blendv_epi8(negativeV, positiveV, mask16iLo); 
__m256i _aHi = _mm256_blendv_epi8(negativeV, positiveV, mask16iHi); 

_mm256_storeu_si256((__m256i*)a + 0, _aLo); 
_mm256_storeu_si256((__m256i*)a + 1, _aHi); 
関連する問題