2017-02-21 67 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_cmpeq_epi8 для создания векторной маски, после того, что я могу использовать _mm256_and_si256 и _mm256_andnot_si256 для выполнения значения выбора.
Проблема: b [i] - 8-битное целое число, а v - 16 бит.
Если вектор маски похож на {0xff, 0x00, 0xff, 0x00...}, его необходимо развернуть до {0xffff, 0x0000, 0xffff, 0x0000...} для выполнения выбора 16-битного значения.
Как я могу это сделать? (Извините за мой английский)

редактировать:
Я нашел решение с вдохновением от 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); 

 Смежные вопросы

  • Нет связанных вопросов^_^