我個人會避免使用MMX。此外,我會使用明確的存儲而不是隱式的,這往往只對某些編譯器有效。以下代碼可在MSVC2012和SSE 4.1中找到。
請注意,fptr
需要16字節對齊。如果您在64位模式下進行編譯,但在32位模式下進行編譯,則應確保其對齊。
#include <stdio.h>
#include <stdint.h>
#include <smmintrin.h>
void process(float *fptr, int16_t *sptr, __m128 factor)
{
__m128 a = _mm_load_ps(fptr);
__m128 b = _mm_mul_ps(a, factor);
__m128i c = _mm_cvttps_epi32(b);
__m128i d = _mm_packs_epi32(c,c);
_mm_storel_epi64((__m128i*)sptr, d);
}
int main() {
float x[] = {1.0, 2.0, 3.0, 4.0};
int16_t y[4];
__m128 factor = _mm_set1_ps(3.14159f);
process(x, y, factor);
printf("%d %d %d %d\n", y[0], y[1], y[2], y[3]);
}
注意_mm_cvtps_pi16
不是一個簡單的稟英特爾內在指南說,「這內在創建的兩個或多個指令序列,並可能比原生指令執行差。考慮這種內在的性能影響。」
下面是使用MMX版本
mulps (%rdi), %xmm0
roundps $0, %xmm0, %xmm0
movaps %xmm0, %xmm1
cvtps2pi %xmm0, %mm0
movhlps %xmm0, %xmm1
cvtps2pi %xmm1, %mm1
packssdw %mm1, %mm0
movq %mm0, (%rsi)
ret
這裏裝配輸出裝配輸出尤斯上交所唯一版本
mulps (%rdi), %xmm0
cvttps2dq %xmm0, %xmm0
packssdw %xmm0, %xmm0
movq %xmm0, (%rsi)
ret
這正是我想要的!但是應該使用_mm_packs_epi32來代替_mm_packus_epi32來保留有符號的值,或者我錯了嗎? – plasmacel
是的,我糾正了我的答案。 –
除了SSE速度更快之外,使用MMX可以使您找到省略EMMS的錯誤(如本例中所示),這是一個嚴重的錯誤(當一些顯然無關的FP計算數百萬個週期後,嚴重的診斷非常難以診斷開始行爲不端)。只要對MMX說不。 –