【发布时间】:2016-08-16 08:46:26
【问题描述】:
我正在尝试熟悉一些较新的英特尔处理器上可用的 256 位 AVX 指令。我已经验证我的 i7-4720HQ 支持 256 位 AVX 指令。我遇到的问题是,应该复制 8 个单精度浮点值的 VMOVAPS 指令只复制了 4 个。
dot PROC
VMOVAPS YMM1, ymmword ptr [RCX]
VDPPS YMM2, YMM1, ymmword ptr [RDX], 255
VMOVAPS ymmword ptr [RCX], YMM2
MOVSS XMM0, DWORD PTR [RCX]
RET
dot ENDP
如果您不熟悉调用约定,Visual C++ 2015 预计此函数的返回值(因为它是一个浮点数)在返回时为 XMM0。
除此之外,标准是第一个参数在 RCX 中传递,第二个参数在 RDX 中传递。
这里是调用这个函数的 C 代码。
_declspec(align(32)) float d1[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
_declspec(align(32)) float d2[] = { 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f };
printf("Dot Product Test: %f\n", dot(d1, d2));
点函数的返回值总是8.0。除此之外,我调试了函数,发现在第一条汇编指令之后,只有四个值被复制到 YMM1 中。 YMM1 的其余部分保持为零。
我在这里做错了吗?我查看了英特尔文档和一些第三方文档。据我所知,我做的一切都是正确的。我是否使用了错误的指令?顺便说一句,如果您是来告诉我使用 Intel 编译器内部函数的,请不要打扰。
【问题讨论】:
-
通过使用
ymm0作为vdpps的目标,您可以在更少的指令中获得相同的(非工作)行为。然后你不需要存储或重新加载,只需返回。如果__vectorcallABI 与 SysV ABI 类似,则您可以将非零垃圾留在保持返回值的位之外的部分寄存器中。 (例如,向量 reg 的高元素)。对于这么小的函数,用 asm 手工编写而不是可以内联的东西意味着函数调用开销可能很大。特别是。因为你通过 ref 传递 args,而不是向量 regs。 -
我刚刚用两分钟写了这段代码来测试汇编指令。我很清楚它可以被优化。