1

我想对 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 进行手动矢量化的经验,所以请告诉我应该如何在这里定义所有类型。

4

1 回答 1

3

你可以把它写成a[n] -= p[n] & ~(a[n] < p[n]). 请注意,<这里不是 C 的,而是 SSE 的 ( pcmpltd),它在每个真元素中返回 -1,在每个假元素中返回 0(以允许 AND 操作),并且&~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));
于 2011-03-13T02:42:46.110 回答