什么是使用SSE 4个浮点乘4辆花车的最有效方法是什么?
题
我现在有以下代码:
float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };
asm volatile("movups (%0), %%xmm0\n\t"
"mulps (%1), %%xmm0\n\t"
"movups %%xmm0, (%1)"
:: "r" (a), "r" (b));
我首先是几个问题:
(1)如果我要对齐于16字节的边界阵列,将它甚至工作?由于阵列在栈上分配是不是真的对准它们几乎是不可能的?
看到所选答案为此信息:由GCC __attribute __((对准对准堆栈变量(X)) )?
(2)可以将代码在所有重构,使之更有效?如果我把两个浮标阵在寄存器中,而不只是一个?
由于
解决方案
如果我被对齐于16字节的边界阵列,将它甚至工作?由于阵列在栈上分配是不是真的对准它们几乎是不可能的?
这是要求在栈上对准的工作原理。否则内部函数是行不通的。我猜你报后曾与他选择的校准值过高的数值做。
至2:
没有,不应该有性能差异。看到此网站几个处理器的指令时序。
堆栈变量的取向如何工作的:
push ebp
mov ebp, esp
and esp, -16 ; fffffff0H
sub esp, 200 ; 000000c8H
在和对齐堆的开始的16字节。
其他提示
它写在C,使用
gcc -S -mssse3
如果你有一个相当新的gcc版本。
(1)如果我是对齐阵列上16个字节的边界上,将它甚至工作?由于阵列在栈上分配是不是真的对准它们几乎是不可能的?
没有,这是相当简单的使用and
对准堆栈指针:
and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary
但是,你应该使用什么GCC提供,如一个16个字节的类型,或__attribute__
定制对准。
是否GCC提供用于__m128
数据类型支持吗?如果是这样这对保证一个16字节对齐数据类型的最佳方案。不过有对准东西__attribute__((aligned(16)))
。定义阵列如下
float a[4] __attribute__((aligned(16))) = { 10, 20, 30, 40 };
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };
和然后使用MOVAPS代替:)
使用固有快得多尤其是与优化。 我写简单的测试,并比较两版本(ASM和本征)
unsigned long long time1;
__m128 a1,b1;
a1=_mm_set_ps(10, 20,30,40);
b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);
float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };
time1=__rdtsc();
a1=_mm_mul_ps(a1,b1);
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);
time1=__rdtsc();
asm volatile("movups (%0), %%xmm0\n\t"
"mulps (%1), %%xmm0\n\t"
"movups %%xmm0, (%1)"
:: "r" (a), "r" (b));
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);
内在版本50-60处理器时间戳 ASM版〜1000个PROC时间戳
您可以测试你的机器上
关于重构。您可以使用固有的。 例如:
#include <emmintrin.h>
int main(void)
{
__m128 a1,b1;
a1=_mm_set_ps(10, 20,30,40);
b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);
a1=_mm_mul_ps(a1,b1);
return 0;
}
使用优化的gcc(-O2
,-O3
)它可以是工作更快然后ASM。
不隶属于 StackOverflow