gpt4 book ai didi

c - 用于复数乘法的汇编代码/AVX 指令。 (GCC 内联汇编)

转载 作者:太空狗 更新时间:2023-10-29 17:08:50 26 4
gpt4 key购买 nike

我们正在运行一个科学程序,我们希望实现 AVX 功能。整个程序(用 Fortran+C 编写)将被矢量化,目前我正在尝试在 GCC 内联汇编中实现复数乘法。

汇编代码接受 4 个复数并一次执行两个复数乘法:

v2complex cmult(v2complex *a, v2complex *b) {
v2complex ret;
asm (
"vmovupd %2,%%ymm1;"
"vmovupd %2, %%ymm2;"
"vmovddup %%ymm2, %%ymm2;"
"vshufpd $15,%%ymm1,%%ymm1,%%ymm1;"
"vmulpd %1, %%ymm2, %%ymm2;"
"vmulpd %1, %%ymm1, %%ymm1;"
"vshufpd $5,%%ymm1,%%ymm1, %%ymm1;"
"vaddsubpd %%ymm1, %%ymm2,%%ymm1;"
"vmovupd %%ymm1, %0;"
:
"=m"(ret)
:
"m" (*a),
"m" (*b)
);
return ret;
}

其中 a 和 b 是 256 位 double :

typedef union v2complex {
__m256d v;
complex c[2];
} v2complex;

问题是代码大部分会产生正确的结果,但有时会失败。

我对汇编很陌生,但我试着自己弄明白。似乎 C 程序(优化的 -O3)与汇编代码中使用的寄存器 ymm 交互。例如,我可以在执行乘法之前打印其中一个值(例如 a),程序永远不会给出错误的结果。

我的问题是如何告诉 GCC 不要与 ymm 交互。我没能做到将 ymm 放入破坏的寄存器列表。

最佳答案

如您所料,问题在于您没有告诉 GCC 您正在破坏哪些寄存器。如果他们还不支持将 YMM 寄存器放入 clobber 列表中,我会感到很惊讶;您使用的是什么版本的 GCC?

无论如何,将相应的 XMM 寄存器放入 clobber 列表中几乎肯定就足够了:

: "=m" (ret) : "m" (*a), "m" (*b) : "%xmm1", "%xmm2");

一些其他注意事项:

  • 您将两个输入都加载了两次,效率很低。没有理由这样做。
  • 我会使用 "r"(a), "r"(b) 作为约束并编写我的负载,例如 vmovupd (%2), %%ymm1。生成的代码可能没有区别,但它似乎更符合惯用语。
  • 在执行任何 SSE 代码之前,不要忘记在 AVX 代码之后放置一个 vzeroupper 以避免(大)停顿。

关于c - 用于复数乘法的汇编代码/AVX 指令。 (GCC 内联汇编),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15766921/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com