MMX和SSE的運用

2021-06-27 04:24:59 字數 2472 閱讀 4350

intel的mmx技術是對intel體系結構(ia)指令集的擴充套件。該技術使用了單指令多資料技術(simd)技術,以並行方式處理多個資料元素。mmx指令集增加了57條新的操作碼和乙個新的64位四字資料型別,增加了八個新的64位mmx暫存器,每個暫存器可按名稱mm0-mm7直接訪問。這意味著我們可以在乙個暫存器裡最多存8個資料(最小單位位元組)。 

sse系列是mmx的超集,直到sse2才跟mmx有本質的區別,新增了對64位雙精度浮點數的支援,以及對整型資料的支援,也就是說這個指令集中所有的mmx指令都是多餘的了,同時也避免了占用浮點數暫存器。這個指令集還增加了對cpu的快取的控制指令。新的sse暫存器命名為xmm0~xmm7,每個128位。 

對h264的優化主要用到了mmx和sse2。舉個例子,在h264解碼端的idct和quant裡,要操作的數是乙個4x4的矩陣,很適合拿來優化。 idct計算公式:

其中,「ei

」已在前面的反量化中完成,其結果為

wr,所以這裡只進行以下運算:

在反變換過程中,可以分成兩次一維變換,使用了蝶形演算法來簡化運算。 原函式就不給了,直接看優化完成後的優化**: 

memcpy(&m7,(&img->cof[i0][j0][0][0]),sizeof(short)*16);

//如果不能採用陣列形式的話,輸入輸出將十分的麻煩。只能通過移位指令,浪費大量的時間。 

_mm_prefetch(&m7,_mm_hint_nta);

//  _mm_prefetch將資料預存到cache裡,一次存乙個cache line的資料,_mm_hint_nta表示存到離cpu最近的cache裡(既l1 cache)。在操作開始前執行_mm_prefetch可以避免由於讀未命中產生的大量延時。

_asm

畫素恢復操作:

img->m7[i][j] =max(0,min(img->max_imgpel_value,( img->m7[i][j] +((long)img->mpr[i+ioff][j+joff] <<6)+32)>>6));

img->m7[i][j1]=max(0,min(img->max_imgpel_value,( img->m7[i][j1]+((long)img->mpr[i+ioff][j1+joff]<<6)+32)>>6)); 

mmx裡沒有max和min相關的指令操作,因此用sse2進行優化。intel提供了intrinsics庫讓我們寫sse**更方便快速,但是這樣會比彙編**要慢,因為它不在乎暫存器的分配和重新使用。

舉個例子: 

temp_m70_sse=_mm_slli_epi16(temp_m70_sse,6); 

_asm 

temp_m70_sse=_mm_add_epi16(temp_m70_sse,temp_32_sse); 

_asm 

可以看到,運用這些指令的時候,每條指令都被單獨的處理,沒有考慮前後相關性,導致資料多次進行訪問,降低了速度,有可能比原來的c語言更慢。 剩下沒什麼好說的,優化後的**如下:

temp_32_sse=_mm_set1_epi16(32); 

m70_sse=_mm_set_epi16(i16a[13],i16a[9],i16a[5],i16a[1],i16a[12],i16a[8],i16a[4],i16a[0]); //由於要處理的資料在記憶體上不是連續的,因此把這些資料讀到xmm暫存器裡會耗費大量時間,編譯後看反彙編的的**就知道了。 m71_sse=_mm_set_epi16(i16a[15],i16a[11],i16a[7],i16a[3],i16a[14],i16a[10],i16a[6],i16a[2]); temp_255_sse=_mm_set1_epi16(img->max_imgpel_value); temp_zero_sse=_mm_set1_epi16(0); temp_m70_sse=_mm_set_epi16(img->mpr[i1_ioff][3+joff],img->mpr[i1_ioff][2+joff],img->mpr[i1_ioff][1+joff],img->mpr[i1_ioff][joff], img->mpr[i0_ioff][3+joff],img->mpr[i0_ioff][2+joff],img->mpr[i0_ioff][1+joff],img->mpr[i0_ioff][joff]); 

temp_m71_sse=_mm_set_epi16(img->mpr[i3_ioff][3+joff],img->mpr[i3_ioff][2+joff],img->mpr[i3_ioff][1+joff],img->mpr[i3_ioff][joff], img->mpr[i2_ioff][3+joff],img->mpr[i2_ioff][2+joff],img->mpr[i2_ioff][1+joff],img->mpr[i2_ioff][joff]);

_asm

_mm_storeu_si128(img_m7,temp_m70_sse);//sse使用專用的結構_m128i,因此最後需要存到我們自己的陣列裡

mmx的32位alpha混合

碰到個古老的問題,畫素的alpha混合,於是查閱了mmx指令,寫出了如下32位畫素格式的alpha混合,不過alpha值固定為半透明,效率還能接受。如下 mov eax,dest dest是目的畫素指標 movd mm0,eax 把目的畫素值移入mm0暫存器的低32位 movd mm1,color ...

SSE的指令系統

sse的指令系統 sse2和sse的指令系統非常相似,僅僅多了少量額外的浮點運算,64位浮點 整數運算支援 sse比傳統浮點運算要快,因為它使用128位儲存單元。在windows使用 include 在linux下使用 include 1.變數定義和使用 m128 s1 s1.m128 f32 2 ...

SSE指令的使用學習

1.什麼是指令集?指令集是為了增強cpu在某些方面 如多 的功能而特意開發出的一組程式 集合。2.常見的指令集有哪些呢?1 mmx multi media extensions,做 擴充套件 指令集 intel1996年推出的一項多 指令增強技術。共包含57條多 指令,這些指令一次可以處理多個資料。...