[英]What's the most efficient way to multiply 4 floats by 4 floats using SSE?
我目前有以下代碼:
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)代碼是否可以重構以提高效率? 如果我將兩個浮點數組都放在寄存器而不只是一個?
謝謝
用C寫,用
gcc -S -mssse3
如果你有一個相當新版本的gcc。
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而不是:)
如果我想在16字節邊界上對齊數組,它甚至可以工作嗎? 由於數組是在堆棧上分配的,因此對齊它們幾乎是不可能的嗎?
要求堆棧上的對齊有效。 否則內在函數不起作用。 我猜你引用的帖子與他為對齊值選擇的過高價值有關。
到2:
不,性能不應該有差異。 有關多個處理器的指令時序,請參閱此站點 。
堆棧變量的對齊方式如何工作:
push ebp
mov ebp, esp
and esp, -16 ; fffffff0H
sub esp, 200 ; 000000c8H
並將堆棧的開頭與16字節對齊。
(1)如果我想在16字節邊界上對齊數組,它甚至可以工作嗎? 由於數組是在堆棧上分配的,因此對齊它們幾乎是不可能的嗎?
不,使用and
對齊堆棧指針非常簡單:
and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary
但是你應該使用GCC提供的內容,例如16字節類型或__attribute__
來自定義對齊。
使用內在更快,特別是在優化時。 我寫了簡單的測試並比較兩個版本(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時間戳
您可以在您的機器上進行測試
關於重構。 你可以使用內在的。 例:
#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工作得更快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.