Конвертировать (векторизовать) код с условным per32-битным элементом в SSE2 SSE3 - PullRequest
1 голос
/ 13 марта 2011

Я хочу векторизовать код для Core2.Я думаю, я могу использовать встроенные функции из gcc или icc, и инструкции SSE, SSE2, SSE3, SSSE3 разрешены.

Мой код работает с массивами из 8 элементов uint32_t, и это так (только горячая точказдесь):

const uint32_t p[8] = {2147483743, 2147483713, 2147483693, 2147483659, 
 2147483647, 2147483629, 2147483587, 2147483579};
void vector_mod_add(uint32_t *a /* a[8] */, uint32_t *b /* b[8] */) {
    int n;
    for(n=0;n<8;n++)
        a[n]+=b[n];
    for(n=0;n<8;n++)
        if(a[n]>=p[n])
            a[n]-=p[n];
}

Добавление довольно простое, но я не знаю, как можно сделать условное вычитание.

Кроме того, у меня нет опыта в ручной векторизации с SSE2Итак, пожалуйста, скажите мне, как мне определить все типы здесь.

1 Ответ

3 голосов
/ 13 марта 2011

Вы можете написать это как a[n] -= p[n] & ~(a[n] < p[n]). Обратите внимание, что < здесь не C, а SSE (pcmpltd), который возвращает -1 в каждом элементе true и 0 в каждом элементе false (чтобы разрешить операцию AND), а &~ is pandn. Вот попытка кода:

__m128i a, p;
a = _mm_sub_epi32(a, _mm_andnot_si128(_mm_cmplt_epi32(a, p), p));

Обратите внимание, что для этого используются подписанные операции, и поэтому ваши номера должны оставаться ниже 2^31 - 1, чтобы они работали правильно. Если вам нужно выйти за пределы этого, измените _mm_cmplt_epi32(a, p) на _mm_cmplt_epi32(_mm_xor_si128(a, signs), _mm_xor_si128(p, signs)), где signs - это вектор 32-битных слов, все элементы которых 0x80000000. Вот версия, которая, кажется, будет обрабатывать более широкие диапазоны более эффективно:

__m128i a, p;
a = _mm_sub_epi32(a, p);
a = _mm_add_epi32(a, _mm_and_si128(_mm_srai_epi32(a, 31), p));
...