以下所有说明都做同样的事情:设置%eax为零.哪种方式最佳(需要最少的机器周期)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
Run Code Online (Sandbox Code Playgroud) 你有一个三(或四)个浮点数的向量.总结它们的最快方法是什么?
SSE(movaps,shuffle,add,movd)总是比x87快吗?SSE4.2中的水平加法说明值得吗?移动到FPU的成本是多少,然后是faddp,faddp?什么是最快的特定指令序列?
"尝试安排事情,这样你可以一次总结四个向量"将不被接受作为答案.:-)
我没有特定的用例; 我问这是否真的是英特尔内在函数中的设计缺陷/限制,或者我是否只是遗漏了某些内容.
如果你想将标量浮点数与现有向量相结合,那么在没有高元素归零或使用英特尔内在函数将标量广播到向量中的情况下似乎没有办法实现.我没有研究过GNU C本机向量扩展和相关的内置函数.
如果额外的内在优化了,这不会太糟糕,但它不与gcc(5.4或6.2).也没有好的方法可以使用pmovzx或insertps作为负载,因为他们的内在函数只采用向量args的相关原因.(并且gcc不会将标量 - >向量加载到asm指令中.)
__m128 replace_lower_two_elements(__m128 v, float x) {
__m128 xv = _mm_set_ss(x); // WANTED: something else for this step, some compilers actually compile this to a separate insn
return _mm_shuffle_ps(v, xv, 0); // lower 2 elements are both x, and the garbage is gone
}
Run Code Online (Sandbox Code Playgroud)
gcc 5.3 -march = nehalem -O3输出,启用SSE4.1并调整该Intel CPU :(没有SSE4.1会更糟;多个指令将上层元素归零).
insertps xmm1, xmm1, 0xe # pointless zeroing of upper elements. shufps only reads the low element of xmm1 …Run Code Online (Sandbox Code Playgroud) 除了其他方面,x86-64 SysV ABI指定了如何在寄存器中传递函数参数(第一个参数in rdi,then rsi等等),以及如何传回整数返回值(in rax和then rdx表示非常大的值).
然而,我找不到的是当传递小于64位的类型时,参数或返回值寄存器的高位应该是什么.
例如,对于以下功能:
void foo(unsigned x, unsigned y);
Run Code Online (Sandbox Code Playgroud)
... x将被传入rdi和y在rsi,但他们只是32位.不要的高32位rdi和rsi必须为零?直观地说,我会假设是,但是所有gcc,clang和icc 生成的代码mov在开始时都有特定的指令将高位清零,所以看起来编译器假定不然.
类似地,编译器似乎假设rax如果返回值小于64 位,则返回值的高位可能具有垃圾位.例如,以下代码中的循环:
unsigned gives32();
unsigned short gives16();
long sum32_64() {
long total = 0;
for (int i=1000; i--; ) {
total += gives32();
}
return total;
}
long sum16_64() {
long total = 0;
for (int i=1000; i--; ) {
total += …Run Code Online (Sandbox Code Playgroud) 我正在为二维卷积编写SSE代码,但SSE文档非常稀疏.我正在使用_mm_dp_ps计算点积并使用_mm_extract_ps来获得点积结果,但_mm_extract_ps返回表示浮点数的十六进制,我无法弄清楚如何将此十六进制浮点数转换为常规浮点数.我可以使用返回浮点数的__builtin_ia32_vec_ext_v4sf,但我想保持与其他编译器的兼容性.
_mm_extract_ps (__m128 __X, const int __N)
{
union { int i; float f; } __tmp;
__tmp.f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N);
return __tmp.i;
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
感谢一点帮助.
OpenSUSE 11.2
GCC 4.4.1
C++
编译器选项
-fopenmp -Wall -O3 -msse4.1 -march = core2
链接器选项
-lgomp -Wall -O3 -msse4.1 -march = core2
如何将128位xmm寄存器拆分为两个64位quadwords?
我输入的字数非常多xmm1,想要将较高的四字r9和较低的四字输入r10,或RAX和RDX。
movlpd或movhpd仅与reg到mem兼容,反之亦然。
VS2019,发布,x86.
template <int i> float get() const {
int f = _mm_extract_ps(fmm, i);
return (float const&)f;
}
Run Code Online (Sandbox Code Playgroud)
使用return (float&)f;编译器时使用
extractps m32, ...
movss xmm0, m32
Run Code Online (Sandbox Code Playgroud)
.正确的结果
使用return (float const&)f;编译器时使用
extractps eax, ...
movd xmm0, eax
Run Code Online (Sandbox Code Playgroud)
.错误的结果
T&和T const&首先是T然后是const的主要思想.Const只是程序员的某种协议.你知道你可以解决它.但汇编代码中没有任何const,但是类型为float IS.我认为对于float和float const而言它必须是汇编中的浮点表示(cpu寄存器).我们可以使用中间int reg32,但最终解释必须是float.
而此时它看起来像回归,因为这之前工作正常.并且在这种情况下使用float也绝对是奇怪的,因为我们不应该考虑浮动const和安全性而是浮动的临时变量并且确实值得怀疑.
微软回答:
嗨Truthfinder,感谢自成一体的复制品.碰巧,这种行为实际上是正确的.正如我的同事@Xiang Fan [MSFT]在内部电子邮件中所述:
由[a c-style cast]执行的转换尝试以下序列:(4.1) - const_cast(7.6.1.11),(4.2) - static_cast(7.6.1.9),(4.3) - static_cast后跟const_cast ,(4.4) - reinterpret_cast(7.6.1.10)或(4.5) - reinterpret_cast后跟const_cast,
如果转换可以用上面列出的多种方式解释,则使用列表中首先出现的解释.
所以在你的情况下,(const float&)被转换为static_cast,其效果是"初始化表达式被隐式转换为类型为"cv1 T1"的prvalue.应用临时实现转换并将引用绑定到结果".
但在另一种情况下,(float&)被转换为reinterpret_cast,因为static_cast无效,这与reinterpret_cast(&operand)相同.
您正在观察的实际"错误"是一个强制转换:"将浮点型值"1.0"转换为等效的int-typed值"1"",而另一个强制转换说"将1.0的位表示形式转换为一个浮点数,然后将这些位解释为int".
出于这个原因,我们建议不要使用c风格的演员表.
谢谢!
MS论坛链接:https://developercommunity.visualstudio.com/content/problem/411552/extract-ps-intrinsics-bug.html
有任何想法吗?
PS我真正想要的是什么:
float val …Run Code Online (Sandbox Code Playgroud) 所以我阅读了英特尔关于 _mm_blendv_ps 的文档,但不太明白该函数的真正作用。所以我写了下面的代码:
__m128 a = { 18.0,4.0,19.0,21.0 };
__m128 b = { 67.0,92.0,888.0,47.0 };
__m128 mask = { 1.0,0.0,0.0,1.0 };
__m128 result = _mm_blendv_ps(a, b, mask);
cout << "Result is: " << result[0] << " " << result[1] << " " << result[2] << " " << result[4] << endl;
Run Code Online (Sandbox Code Playgroud)
但我收到错误“没有运算符 [] 与这些操作数匹配”。为什么我无法访问结果?结果不是32位浮点向量吗?
那么为什么我无法访问结果呢?我怎样才能访问它?cout 的结果是什么(blendv 做什么)?
sse ×7
x86 ×6
assembly ×4
c++ ×3
gcc ×3
c ×2
intrinsics ×2
optimization ×2
simd ×2
hex ×1
linux ×1
performance ×1
visual-c++ ×1
x86-64 ×1