gpt4 book ai didi

c - 如何更新矢量化汇编(AVX)中的数组?

转载 作者:行者123 更新时间:2023-11-30 20:48:39 25 4
gpt4 key购买 nike

inline void addition(double * x, const double * vx,uint32_t size){
/*for (uint32_t i=0;i<size;++i){
x[i] = x[i] + vx[i];
}*/
__asm__ __volatile__ (
"1: \n\t"

"vmovupd -32(%0), %%ymm1\n\t"
"vmovupd (%0), %%ymm0\n\t"
"vaddpd -32(%1), %%ymm0, %%ymm0\n\t"
"vaddpd (%1), %%ymm1, %%ymm1\n\t"

"vmovupd %%ymm0, -32(%0)\n\t"
"vmovupd %%ymm1, (%0)\n\t"

"addq $128, %0\n\t"
"addq $128, %1\n\t"

"addl $-8, %2\n\t"
"jne 1b"
:
: "r" (x),"r"(vx),"r"(size)
: "ymm0", "ymm1"
);
}

我现在正在练习汇编(AVX指令),所以我在内联汇编中编写了上面的代码来替换原始函数中的c代码(已被注释掉)。编译过程成功,但是当我尝试运行该程序时,发生错误:总线错误:10对这个错误有什么想法吗?我不知道这里出了什么问题。编译器版本是 clang 602.0.53。谢谢!

最佳答案

内联汇编是一个复杂的野兽,如果您只想练习 AVX 汇编,请使用单独的 asm 文件,而不必忍受编译器。作为交换,您需要遵守调用约定。

您对限制有一些疑问。例如,您在不告诉编译器的情况下更改了所有输入寄存器,这可能会在编译器生成的代码中的其他地方导致各种奇怪的问题。出于显而易见的原因,您还需要指定一个内存破坏者。

此外,学习使用调试器,以便找到问题的确切原因并修复您自己的代码。

如果做不到这一点,至少注释一下您的代码,以便我们能够弄清楚您的意图。在这种情况下,我特别不解为什么在数组之前使用-32偏移量来寻址。我想你想要的是+32。使用两个每个 32 字节的 avx 寄存器,您当然需要将指针前进 64 而不是 128。此外,您在初始加载中交换了 ymm0ymm1 。 p>

这段代码似乎对我来说工作得很好:

#include <stdio.h>
#include <stdint.h>

inline void addition(double * x, const double * vx,uint32_t size){
/*for (uint32_t i=0;i<size;++i){
x[i] = x[i] + vx[i];
}*/
__asm__ __volatile__ (
"1: \n\t"

"vmovupd 32(%0), %%ymm0\n\t"
"vmovupd (%0), %%ymm1\n\t"
"vaddpd 32(%1), %%ymm0, %%ymm0\n\t"
"vaddpd (%1), %%ymm1, %%ymm1\n\t"

"vmovupd %%ymm0, 32(%0)\n\t"
"vmovupd %%ymm1, (%0)\n\t"

"addq $64, %0\n\t"
"addq $64, %1\n\t"

"addl $-8, %2\n\t"
"jne 1b"
: "+r" (x),"+r"(vx),"+r"(size)
:
: "ymm0", "ymm1", "memory"
);
}

int main()
{
double x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
double vx[] = { 9, 10, 11, 12, 13, 14, 15, 16 };
int i;
addition(x, vx, 8);
for(i = 0; i < 8; i++) printf("%g ", x[i]);
putchar('\n');
return 0;
}

关于c - 如何更新矢量化汇编(AVX)中的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35261056/

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