我试图了解以下代码片段的工作原理。该程序使用 SIMD 向量指令(英特尔 SSE)来计算 4 个浮点数的绝对值(因此,基本上,一个向量化的“fabs()”函数)。
这是片段:
#include <iostream>
#include "xmmintrin.h"
template <typename T>
struct alignas(16) sse_t
{
T data[16/sizeof(T)];
};
int main()
{
sse_t<float> x;
x.data[0] = -4.;
x.data[1] = -20.;
x.data[2] = 15.;
x.data[3] = -143.;
__m128 a = _mm_set_ps1(-0.0); // ???
__m128 xv = _mm_load_ps(x.data);
xv = _mm_andnot_ps(a,xv); // <-- Computes absolute value
sse_t<float> result;
_mm_store_ps(result.data, xv);
std::cout << "x[0]: " << result.data[0] << std::endl;
std::cout << "x[1]: " << result.data[1] << std::endl;
std::cout << "x[2]: " << result.data[2] << std::endl;
std::cout << "x[3]: " << result.data[3] << std::endl;
}
现在,我知道它有效,因为我自己运行程序来测试它。使用 g++ 4.8.2 编译时,结果为:
x[0]: 4
x[1]: 20
x[2]: 15
x[3]: 143
三个(相关的)问题让我感到困惑:
首先,怎么可能采用按位函数并将其应用于浮点数?如果我在 vanilla C++ 中尝试这个,它会告诉我这只适用于整数类型(这是有道理的)。
但是,第二,更重要的是:它是如何工作的?在这里接受 NOT 和 AND 对您有什么帮助?在 Python 中尝试使用整数类型只会给您预期的结果:任何整数 AND -1(不是 0),只会返回该数字,但不会更改符号。那么它在这里是如何工作的呢?
第三,我注意到如果我将用于 NAND 操作的浮点值(标有三个???)从 -0.0 更改为 0.0,程序不再给我绝对值。但是 -0.0 怎么可能存在,它有什么帮助呢?
有用的参考资料: