我最近以内在函数的形式使用了x86 SIMD指令(SSE1234).我发现令人沮丧的是,SSE ISA有几个简单的指令,只能用于浮点数或仅用于整数,但理论上它们应该同样适用于两者.例如,float和double向量都有指令从地址(movhps,movhpd)加载更高的64位128位向量,但是没有这样的整数向量指令.
我的问题:
在整数向量上使用浮点指令时是否有任何理由期望性能受到影响,例如使用movhps将数据加载到整数向量?
我写了几个测试来检查,但我认为他们的结果不可信.编写一个正确的测试来探索这些事情的所有极端情况真的很难,特别是在这里可能涉及指令调度时.
相关问题:
其他平凡相似的东西也有几个基本相同的指令.例如,我可以使用por,orps或orpd按位OR .任何人都可以解释这些附加说明的目的是什么?我想这可能与应用于每条指令的不同调度算法有关.
许多SSE"mov"指令指定它们正在移动浮点值.例如:
为什么这些指令只是说它们移动32位或64位值?如果它们只是移动位,为什么指令指定它们是浮点值?当然,无论你是否将这些位解释为浮点,它们都能工作吗?
AVX允许按位逻辑运算,例如和/或浮点数据类型__m256和__m256d.
但是,C++不允许合理地对浮点数和双精度数进行逐位运算.如果我是对的,不能保证浮点数的内部表示,无论编译器是否使用IEEE754,因此程序员无法确定浮点数的位置是什么样的.
考虑这个例子:
#include <immintrin.h>
#include <iostream>
#include <limits>
#include <cassert>
int main() {
float x[8] = {1,2,3,4,5,6,7,8};
float mask[8] = {-1,0,0,-1,0,-1,0,0};
float x_masked[8];
assert(std::numeric_limits<float>::is_iec559);
__m256 x_ = _mm256_load_ps(x);
__m256 mask_ = _mm256_load_ps(mask);
__m256 x_masked_ = _mm256_and_ps(x_,mask_);
_mm256_store_ps(x_masked,x_masked_);
for(int i = 0; i < 8; i++)
std::cout << x_masked[i] << " ";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
假设使用IEEE754,因为-1的表示是0xffffffff,我希望输出为
1,0,0,4,0,6,0,0
Run Code Online (Sandbox Code Playgroud)
而它反而是
1 0 0 1.17549e-38 0 1.17549e-38 0 0
Run Code Online (Sandbox Code Playgroud)
因此,我对内部表征的假设可能是错误的(或者我犯了一些愚蠢的错误).
所以问题是:有没有一种方法可以使用浮点逻辑并且对结果有意义的事实保持安全?