【发布时间】:2016-05-14 06:37:35
【问题描述】:
我是 SSE 内在函数的新手,并尝试通过它优化我的代码。这是我关于计算等于给定值的数组元素的程序。
我将代码更改为 SSE 版本,但速度几乎没有变化。我想知道我是否以错误的方式使用 SSE...
此代码用于不允许我们启用编译器优化选项的赋值。
没有 SSE 版本:
int get_freq(const float* matrix, float value) {
int freq = 0;
for (ssize_t i = start; i < end; i++) {
if (fabsf(matrix[i] - value) <= FLT_EPSILON) {
freq++;
}
}
return freq;
}
上交所版本:
#include <immintrin.h>
#include <math.h>
#include <float.h>
#define GETLOAD(n) __m128 load##n = _mm_load_ps(&matrix[i + 4 * n])
#define GETEQU(n) __m128 check##n = _mm_and_ps(_mm_cmpeq_ps(load##n, value), and_value)
#define GETCOUNT(n) count = _mm_add_ps(count, check##n)
int get_freq(const float* matrix, float givenValue, ssize_t g_elements) {
int freq = 0;
int i;
__m128 value = _mm_set1_ps(givenValue);
__m128 count = _mm_setzero_ps();
__m128 and_value = _mm_set1_ps(0x00000001);
for (i = 0; i + 15 < g_elements; i += 16) {
GETLOAD(0); GETLOAD(1); GETLOAD(2); GETLOAD(3);
GETEQU(0); GETEQU(1); GETEQU(2); GETEQU(3);
GETCOUNT(0);GETCOUNT(1);GETCOUNT(2);GETCOUNT(3);
}
__m128 shuffle_a = _mm_shuffle_ps(count, count, _MM_SHUFFLE(1, 0, 3, 2));
count = _mm_add_ps(count, shuffle_a);
__m128 shuffle_b = _mm_shuffle_ps(count, count, _MM_SHUFFLE(2, 3, 0, 1));
count = _mm_add_ps(count, shuffle_b);
freq = _mm_cvtss_si32(count);
for (; i < g_elements; i++) {
if (fabsf(matrix[i] - givenValue) <= FLT_EPSILON) {
freq++;
}
}
return freq;
}
【问题讨论】:
-
为什么要关心性能,向量代码甚至还没有正确。
-
你能告诉我错误是什么吗?我会改正的。
-
你不比较
fabs(x) <= FLT_EPSILON,你比较x != 0.0f,完全不等同于非矢量化版本。 -
比较
x != 0.0f还是x == 0.0f不是重点。两者都不等同于fabs(x) <= FLT_EPSILON。不,SSE 不会神奇地使浮点数学变得无限精确。我会说你的测试很糟糕,不要练习FLT_EPSILON相关的情况。当然,无论如何,该测试的价值值得怀疑,但我不是就该主题进行演讲的合适人选。 -
好吧,我还建议您研究一下
FLT_EPSILON的实际 含义,以及它与浮点不准确性的关系。提示:一般不适合作为两个值之差的绝对误差。