SSE - 比较并确定我的价值?

SSE - compare and put my value?

我在这个intel intrinsic guide page.

我的 sse 经验有点脆弱。


好的,我有一个名为 'source'.

的数组 - 一个很长的整数数组

示例:

如果它匹配某个值,我想更改它的一些值。

int source[] = {4,5,9,8}
int mask[] = {4,4,4,4}
int replacer[] = {3,3,3,3} 

所以最终的来源应该是这样的 {3,5,9,8}

我想使用 SSE < 4 来实现。

我遇到的最接近的指令是 _mm_cmpeq_epi32:

FOR j := 0 to 3 
i := j*32 dst[i+31:i] := ( a[i+31:i] == b[i+31:i] ) ? 0xFFFFFFFF : 0 
ENDFOR

现在我想要一些东西来用我的值替换原始数组,否则什么也不做:

FOR j := 0 to 3 
i := j*32 dst[i+31:i] := ( a[i+31:i] == b[i+31:i] ) ? my_mask_value_here : source_value_untouched
ENDFOR

是否有远程实现我正在尝试的东西?即使结合不同的指令我也搞不清楚..

谢谢

使用 PCMPEQ 获得掩码后,如果您有 sse 4.1,则可以使用专门用于此目的的 PBLENDVB 指令。否则,您可以使用 PANDPANDNPOR 来模拟它。另外,可以使用MASKMOVDQU

下面是演示这 3 种方式的源代码:

#include <stdio.h>
#include <x86intrin.h>

int main()
{
    int source[] = {4,5,9,8};
    int mask[] = {4,4,4,4};
    int replacer[] = {3,3,3,3};

    __m128i bitmask = _mm_cmpeq_epi32(*(__m128i*)source, *(__m128i*)mask);

    // manual version
    __m128i result = _mm_and_si128(*(__m128i*)replacer, bitmask);
    __m128i tmp = _mm_andnot_si128(bitmask, *(__m128i*)source);
    result = _mm_or_si128(result, tmp);
    printf("%d %d %d %d\n", *(int*)&result, *((int*)&result + 1), *((int*)&result + 2), *((int*)&result + 3));

    // maskmovdqu version
    result = *(__m128i*)source;
    _mm_maskmoveu_si128(*(__m128i*)replacer, bitmask, (char*)&result);
    printf("%d %d %d %d\n", *(int*)&result, *((int*)&result + 1), *((int*)&result + 2), *((int*)&result + 3));

    // sse 4.1 version
    result = _mm_blendv_epi8(*(__m128i*)source, *(__m128i*)replacer, bitmask);
    printf("%d %d %d %d\n", *(int*)&result, *((int*)&result + 1), *((int*)&result + 2), *((int*)&result + 3));
}