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
指令。否则,您可以使用 PAND
、PANDN
和 POR
来模拟它。另外,可以使用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));
}
我在这个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
指令。否则,您可以使用 PAND
、PANDN
和 POR
来模拟它。另外,可以使用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));
}