我是SSE的新手,知识有限。我正在尝试向量化我的代码(C ++,使用gcc),这实际上非常简单。 我有一个无符号整数数组,我只检查> =或< =比某些常量的元素。结果,我需要一个包含传递条件的元素的数组。 我正在考虑使用'mm_cmpge_ps'作为掩码,但这个构造可以在浮点数上工作而不是整数!? :(
任何建议,非常感谢帮助。
答案 0 :(得分:2)
很容易掩盖掉(即设置为0)所有不匹配的整数。 e.g。
#include <emmintrin.h> // SSE2 intrinsics
for (int i = 0; i < N; i += 4)
{
__m128i v = _mm_load_si128(&a[i]);
__m128i vcmp0 = _mm_cmpgt_epi32(v, _mm_set1_epi32(MIN_VAL - 1));
__m128i vcmp1 = _mm_cmplt_epi32(v, _mm_set1_epi32(MAX_VAL + 1));
__m128i vcmp = _mm_and_si128(vcmp0, vcmp1);
v = _mm_and_si128(v, vcmp);
_mm_store_si128(&a[i], v);
}
请注意,a
需要16字节对齐,而N
需要是4的倍数 - 如果这些约束是一个问题,那么扩展代码以应对此问题并不困难。
答案 1 :(得分:1)
你走了。这是三个功能。
第一个函数foo_v1
基于Paul R的答案。
第二个功能foo_v2
基于今天流行的问题Fastest way to determine if an integer is between two integers (inclusive) with known sets of values
第三个函数foo_v3
使用了Agner Fog的vectorclass,我只是为了表明使用他的类更容易和更清洁。如果您没有该课程,则只需注释掉#include "vectorclass.h"
行和foo_v3
功能。我使用Vec8ui
这意味着它将使用AVX2(如果可用)并将其分解为两个Vec4ui,否则您不必更改代码以获得AVX2的好处。
#include <stdio.h>
#include <nmmintrin.h> // SSE4.2
#include "vectorclass.h"
void foo_v1(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
for (int i = 0; i < N; i += 4) {
__m128i v = _mm_load_si128((const __m128i*)&a[i]);
__m128i vcmp0 = _mm_cmpgt_epi32(v, _mm_set1_epi32(MIN_VAL - 1));
__m128i vcmp1 = _mm_cmplt_epi32(v, _mm_set1_epi32(MAX_VAL + 1));
__m128i vcmp = _mm_and_si128(vcmp0, vcmp1);
v = _mm_and_si128(v, vcmp);
_mm_store_si128((__m128i*)&a[i], v);
}
}
void foo_v2(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
//if ((unsigned)(number-lower) < (upper-lower))
for (int i = 0; i < N; i += 4) {
__m128i v = _mm_load_si128((const __m128i*)&a[i]);
__m128i dv = _mm_sub_epi32(v, _mm_set1_epi32(MIN_VAL));
__m128i min_ab = _mm_min_epu32(dv,_mm_set1_epi32(MAX_VAL-MIN_VAL));
__m128i vcmp = _mm_cmpeq_epi32(dv,min_ab);
v = _mm_and_si128(v, vcmp);
_mm_store_si128((__m128i*)&a[i], v);
}
}
void foo_v3(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
//if ((unsigned)(number-lower) < (upper-lower))
for (int i = 0; i < N; i += 8) {
Vec8ui va = Vec8ui().load(&a[i]);
va &= (va - MIN_VAL) <= (MAX_VAL-MIN_VAL);
va.store(&a[i]);
}
}
int main() {
const int N = 16;
int* a = (int*)_mm_malloc(sizeof(int)*N, 16);
for(int i=0; i<N; i++) {
a[i] = i;
}
foo_v2(N, a, 7, 3);
for(int i=0; i<N; i++) {
printf("%d ", a[i]);
} printf("\n");
_mm_free(a);
}
答案 2 :(得分:0)
首先要查看的地方可能是Intel® Intrinsics Guide