2

我目前有以下代码:

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__((aligned(x))) 对齐?

(2) 可以重构代码以提高效率吗?如果我将两个浮点数组都放入寄存器而不是一个呢?

谢谢

4

6 回答 6

7

用C写,使用

gcc -S -mssse3

如果你有一个相当新版本的 gcc。

于 2009-08-04T12:56:35.650 回答
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 :)

于 2009-08-04T12:38:58.267 回答
1

如果我要在 16 字节边界上对齐数组,它甚至可以工作吗?由于数组是在堆栈上分配的,对齐它们几乎是不可能的吗?

要求堆栈上的对齐工作。否则内在函数将不起作用。我猜你引用的帖子与他为对齐值选择的过高值有关。

到 2:

不,性能上应该没有区别。有关多个处理器的指令时序,请参见此站点


堆栈变量的对齐方式如何工作:

push    ebp
mov ebp, esp
and esp, -16                ; fffffff0H
sub esp, 200                ; 000000c8H

将堆栈的开头对齐到 16 字节。

于 2009-08-04T12:44:25.940 回答
1

(1) 如果我要在 16 字节边界上对齐数组,它甚至可以工作吗?由于数组是在堆栈上分配的,对齐它们几乎是不可能的吗?

不,使用以下方法对齐堆栈指针非常简单and

and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary

但是您应该使用 GCC 提供的内容,例如 16 字节类型,或者__attribute__自定义对齐方式。

于 2009-08-04T12:45:16.613 回答
1

使用内在函数要快得多,尤其是在优化时。我写了简单的测试并比较了两个版本(asm和intrinsic)

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 时间戳

你可以在你的机器上测试它

于 2012-11-23T08:42:08.643 回答
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 工作得更快。

于 2012-11-23T07:38:53.527 回答