我目前有以下代码:
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字节边界上对齐数组,它甚至可以工作吗?由于数组是在堆栈上分配的,因此对齐它们几乎是不可能的吗?
查看此帖子的选定答案:Are stack variables aligned by the GCC __attribute__((aligned(x)))?
(2)代码是否可以重构以提高效率?如果我将两个浮点数组都放在寄存器而不只是一个?
,该怎么办?由于
答案 0 :(得分:7)
将其写在C中,使用
gcc -S -mssse3
如果你有一个相当新版本的gcc。
答案 1 :(得分:1)
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:)
答案 2 :(得分:1)
如果我想在16字节边界上对齐数组,它甚至可以工作吗?由于数组是在堆栈上分配的,因此对齐它们几乎是不可能的吗?
要求堆栈上的对齐有效。否则内在函数不起作用。我猜你引用的帖子与他为对齐值选择的过高价值有关。
到2:
不,性能不应该有差异。有关多个处理器的指令时序,请参阅此site。
堆栈变量的对齐方式如何工作:
push ebp
mov ebp, esp
and esp, -16 ; fffffff0H
sub esp, 200 ; 000000c8H
和将堆栈的开头对齐为16字节。
答案 3 :(得分:1)
(1)如果我想在16字节边界上对齐数组,它甚至可以工作吗?由于数组是在堆栈上分配的,因此对齐它们几乎是不可能的吗?
不,使用and
对齐堆栈指针非常简单:
and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary
但你应该使用GCC提供的内容,例如16字节类型,或__attribute__
来自定义对齐。
答案 4 :(得分:1)
使用内在更快,特别是在优化时。 我写了简单的测试并比较了两个版本(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 Version~1000 proc时间戳
您可以在自己的机器上进行测试
答案 5 :(得分:0)
关于重构。你可以使用内在的。 例如:
#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更快。