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

标签 c assembly x86 inline-assembly avx

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/

相关文章:

c - Lua liblua5.1.so 无法打开共享对象文件

c++ - 如何制作一个动态大小的数组?动态数组的一般用法(也可能是指针)?

assembly - 赋值指令未将新值分配给 emu8086 中的符号

.net - 为什么 "vcredist_x86_2010_sp1.exe,Asia"不允许我安装 SQLite?

c - 当 p 指向一个数组(int)索引时, '-1[p]' 是什么?

你能从c中的文件中的特定位置写入吗?

c - 在使用系统调用生成的 printf 上输出两个字符串时遇到问题

组件 IA32 : What's wrong with this piece of code?

x86 - 你会从 DOS 挂断什么中断来获取实时时钟

android - 如何为双显示器配置 Android x86(即克隆)?