2009-08-04 37 views
2

目前,我有以下代碼:使用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字節邊界的數組,將它甚至工作?由於數組是分配在堆棧上的,因此調整它們幾乎是不可能的。

看到所選答案的這篇文章:Are stack variables aligned by the GCC __attribute__((aligned(x)))?

(2)可以將代碼在所有被重構,使之更有效率?如果我將兩個浮點數組都放入寄存器而不只是一個,會怎麼樣?

感謝

回答

1

如果我是對齊16字節邊界的數組,將它甚至工作?由於數組是分配在堆棧上的,因此調整它們幾乎是不可能的。

要求堆疊上的對齊工作。否則內部函數將無法工作。我想你所引用的帖子必須與他選擇的高價值對齊。

以2:

不,不應該有性能差異。有關幾個處理器的指令時序,請參見此site


如何堆棧變量的對齊工作:

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

對齊堆棧的開始16字節。

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代替:)

+0

感謝;但正如本文所述http://stackoverflow.com/questions/841433/gcc-attributealignedx-explanation似乎不可能對齊在堆棧上分配的數組? (而不是全局數組分配在.data中) – horseyguy 2009-08-04 12:44:11

+0

感謝修復Bastien :) Banister ...你能試試看看會發生什麼嗎?如果與解釋相關的是正確的,那麼就不可能像正確地對齊double這樣的東西,然而它們會對齊。 – Goz 2009-08-04 12:55:10

+0

是的,我很快就會......我有一種感覺,相關的解釋是錯誤的,因爲這個問題中的每個人都似乎暗示。感謝大家! :) – horseyguy 2009-08-04 12:58:16

1

(1)如果我需要對齊16個字節邊界上的數組,它會工作嗎?由於數組是分配在堆棧上的,因此調整它們幾乎是不可能的。

沒有,這是很簡單的排列使用and堆棧指針:

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

但是,你應該使用什麼GCC提供,如一個16個字節的類型,或者__attribute__定製校準。

+0

感謝您的回答,您能否向我解釋如何使用'和'進行對齊?我不太''得到它:) – horseyguy 2009-08-05 16:33:48

7

寫在C,使用

gcc -S -mssse3 

,如果你有一個相當新的gcc版本。

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。

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版本〜1000 PROC時間戳

你可以測試你的機器上