如何更新 X86 中双精度数组中的所有元素?
How to update all the elements in a double array in X86?
我是 X86 的新手,我坚持使用另一个双精度数组的值更新双精度数组。下面的代码是我的函数,我想用内联汇编来替换循环内的那段代码。我附上了下面的错误信息。谁能帮我指出我的错误?我对错误信息感到困惑,不知道如何修改。
static inline void update(double * x,double * y,double * z,double * vx,
double * vy,double * vz,uint32_t size){
for (uint32_t i=0;i<size;++i){
x[i] = x[i] + vx[i];
y[i] = y[i] + vy[i];
z[i] = z[i] + vz[i];
}
}
uint32_t counter = 0;
__asm__ __volatile__ (
"loop: \n\t"
"faddq (%4), (%1)\n\t"
"faddq (%5), (%2)\n\t"
"faddq (%6), (%3)\n\t"
"addq , %1\n\t"
"addq , %2\n\t"
"addq , %3\n\t"
"addq , %4\n\t"
"addq , %5\n\t"
"addq , %6\n\t"
"incq %0\n\t"
"cmp %0, %7\n\t"
"jne loopb"
: "+r"(counter)
: "r" (x),"r" (y),"r"(z),"r"(vx),"r"(vy),"r"(vz),"r"(size)
: "memory", "cc");
错误信息:
update_locations_ass.c:150:15: error: invalid instruction mnemonic 'faddq'
"loop: \n\t"
^
<inline asm>:2:2: note: instantiated into assembly here
faddq (%rdi), (%rcx)
^~~~~
update_locations_ass.c:151:25: error: invalid instruction mnemonic 'faddq'
"faddq (%4), (%1)\n\t"
^
<inline asm>:3:2: note: instantiated into assembly here
faddq (%r8), (%rdx)
^~~~~
update_locations_ass.c:152:28: error: invalid instruction mnemonic 'faddq'
"faddq (%5), (%2)\n\t"
^
<inline asm>:4:2: note: instantiated into assembly here
faddq (%r9), (%rsi)
^~~~~
update_locations_ass.c:159:23: error: invalid operand for instruction
"addq , %6\n\t"
^
<inline asm>:11:7: note: instantiated into assembly here
incq %eax
编译器版本:
配置为:--prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM 版本 6.1.0 (clang-602.0.53)(基于 LLVM 3.6.0svn)
目标:x86_64-apple-darwin14.0.0
线程模型:posix
我在这里同样感到困惑。 faddq
是什么,你从哪里得到的?应该是 fadd
吗?无论如何,您不能将两个内存操作数与 fadd
一起使用,因此代码看起来完全不正确。如果您对正确的方法感到好奇,请尝试使用 -S
和 -O2
进行编译,以便查看优化的编译器输出。
如果您想获得该函数的更快版本,最简单的方法就是用 C 来实现。假设数组不重叠,这是一个更快的版本:
// Assuming x and vx do not overlap
void update1(double *restrict x, const double *restrict vx, unsigned count) {
for (unsigned i = 0; i < count; i++) {
x[i] += vx[i];
}
}
void update(/* ... */) {
update1(x, vx, count);
update1(y, vy, count);
update1(z, vz, count);
}
如果您使用 -O3
进行编译,编译器将生成使用 addpd
的代码,具体取决于您的编译目标。这将比您使用 x87 FPU 指令自己编写的任何东西都要好得多。
这些简单的函数——只是将数组添加到其他数组——编译器很容易优化,所以除非你自学汇编语言,否则让编译器为你做。
我是 X86 的新手,我坚持使用另一个双精度数组的值更新双精度数组。下面的代码是我的函数,我想用内联汇编来替换循环内的那段代码。我附上了下面的错误信息。谁能帮我指出我的错误?我对错误信息感到困惑,不知道如何修改。
static inline void update(double * x,double * y,double * z,double * vx,
double * vy,double * vz,uint32_t size){
for (uint32_t i=0;i<size;++i){
x[i] = x[i] + vx[i];
y[i] = y[i] + vy[i];
z[i] = z[i] + vz[i];
}
}
uint32_t counter = 0;
__asm__ __volatile__ (
"loop: \n\t"
"faddq (%4), (%1)\n\t"
"faddq (%5), (%2)\n\t"
"faddq (%6), (%3)\n\t"
"addq , %1\n\t"
"addq , %2\n\t"
"addq , %3\n\t"
"addq , %4\n\t"
"addq , %5\n\t"
"addq , %6\n\t"
"incq %0\n\t"
"cmp %0, %7\n\t"
"jne loopb"
: "+r"(counter)
: "r" (x),"r" (y),"r"(z),"r"(vx),"r"(vy),"r"(vz),"r"(size)
: "memory", "cc");
错误信息:
update_locations_ass.c:150:15: error: invalid instruction mnemonic 'faddq'
"loop: \n\t"
^
<inline asm>:2:2: note: instantiated into assembly here
faddq (%rdi), (%rcx)
^~~~~
update_locations_ass.c:151:25: error: invalid instruction mnemonic 'faddq'
"faddq (%4), (%1)\n\t"
^
<inline asm>:3:2: note: instantiated into assembly here
faddq (%r8), (%rdx)
^~~~~
update_locations_ass.c:152:28: error: invalid instruction mnemonic 'faddq'
"faddq (%5), (%2)\n\t"
^
<inline asm>:4:2: note: instantiated into assembly here
faddq (%r9), (%rsi)
^~~~~
update_locations_ass.c:159:23: error: invalid operand for instruction
"addq , %6\n\t"
^
<inline asm>:11:7: note: instantiated into assembly here
incq %eax
编译器版本: 配置为:--prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM 版本 6.1.0 (clang-602.0.53)(基于 LLVM 3.6.0svn) 目标:x86_64-apple-darwin14.0.0 线程模型:posix
我在这里同样感到困惑。 faddq
是什么,你从哪里得到的?应该是 fadd
吗?无论如何,您不能将两个内存操作数与 fadd
一起使用,因此代码看起来完全不正确。如果您对正确的方法感到好奇,请尝试使用 -S
和 -O2
进行编译,以便查看优化的编译器输出。
如果您想获得该函数的更快版本,最简单的方法就是用 C 来实现。假设数组不重叠,这是一个更快的版本:
// Assuming x and vx do not overlap
void update1(double *restrict x, const double *restrict vx, unsigned count) {
for (unsigned i = 0; i < count; i++) {
x[i] += vx[i];
}
}
void update(/* ... */) {
update1(x, vx, count);
update1(y, vy, count);
update1(z, vz, count);
}
如果您使用 -O3
进行编译,编译器将生成使用 addpd
的代码,具体取决于您的编译目标。这将比您使用 x87 FPU 指令自己编写的任何东西都要好得多。
这些简单的函数——只是将数组添加到其他数组——编译器很容易优化,所以除非你自学汇编语言,否则让编译器为你做。