mmx開發文件

2021-06-06 22:19:50 字數 4177 閱讀 7423

** 

i  mmx簡介

ii  mmx基本指令集

具體細節請參閱《intel 體系結構mmx技術程式設計師參考手冊》第五章           

2.1 拷貝指令

movq:64位資料拷貝,如果記憶體8位對齊的話,是乙個64位寫,否則2個32位寫。

movd:32位資料拷貝,注意:如果從記憶體向mmx暫存器拷貝,mmx高32位清零!

2.2 分組指令

分組指令是mmx特有的,所以對於它我們要特別的關注。分組指令基本上可以分為2類,一類是不帶符號緊縮的,一類是帶符號緊縮的。現在我們分別予以介紹:

①punpcklbw / punpcklwd / punpckldq (l表示低位分組,bw8位,wd16位,dq32位):它是簡單的將兩個mmx暫存器的低32位交錯組合為乙個64位資料。所以它是不能將長資料轉換為短資料的。

②packuswb 將16位資料轉換為無符號的8位資料。所以可以將兩個mmx暫存器不交錯的合為乙個64位資料。

③packsswb/packssdw 將32位-》16位,16位-》8位,都是有符號的資料。

2.3 運算指令

加法運算指令:paddb(w)(d):沒有越界保護的加法,當越界的時候僅僅丟棄超出範圍的高位位元,(b)(w)(d)分別為8,16,32位加法;paddsb(w):具有越界保護的有符號加法,當上溢的時候為0x7fff,下溢的時候為0x8000;paddusb(w):具有越界保護的無符號加法,當上溢的時候為0x7fff,下溢的時候為0x0。

減法運算指令同上;add改為sub。

乘法指令:pmullw  / pmulhw 是4個16位資料的乘法,pmullw中是結果的低16位,pmulhw是結果的高16位。pmaddwd 乘加指令。

2.4 邏輯指令,移位指令和emms指令

細節參見《intel 體系結構mmx技術程式設計師參考手冊》。

iii  mmx經典處理策略

①資料輸入輸出:

在輸入資料的時候,經典的處理方法是將乙個陣列整個「load」到mmx暫存器中。這樣簡單同時利用了mmx64位讀寫資料的能力,提高了效能。同樣在輸出的時候,也是將乙個64位mmx暫存器中的資料內容整個「store」到記憶體中。

如果實在是不能這樣處理的話,就要利用移位指令了。比如說將乙個mmx內的4個16位資料分別拷貝到不同的記憶體變數(或者16位通用暫存器中)x1,x2,x3,x4,那麼可以這樣處理:

movd     eax,mm1

psrlq       mm1,32

movd     ebx,mm1

mov       x1,ax

mov       x2,bx

shr          eax,16

shr          ebx,16

mov        x3,ax

mov        x4,bx

可見如果不採用陣列形式的話,輸入輸出將十分的麻煩。

②資料分組以及求絕對值的方法等:

細節請參閱《intel 體系結構mmx™ 技術開發者手冊》第五章           

iv  自定義組合指令

①八位無符號數的移位:

在mmx指令集中是沒有8位資料的移位指令的,但是有的時候我們確實需要,所以可以用以下兩個指令來實現:

psrlq       mm0,1

pand              mm0,0x7f7f7f7f7f7f7f7f

②如何防止計算過程中越界:

比如在計算的時候,我們有(x1+x2+1)>>1,這個時候x1+x2就會越界(8位資料),那麼我們就不得不使用替代了辦法,比如(x1>>1+x2>>1)這個處理是不精確的,在不需要很精確的場合,是可以使用的,但是如果結果差錯1都不可容忍的話,就要進行一點處理:

pand              mm0,0x01010101010101             //保留資料的最後一位數

pand              mm1,0x01010101010101             //保留資料的最後一位數

por         mm0,mm1                                 

paddusb  mmx,mm0                                  //修正資料

(x1>>2+x2>>2):這個處理是通用的

pand              mm0,0x03030303030303             //保留資料的最後兩位數

pand              mm1, 0x03030303030303            //保留資料的最後兩位數

paddusb  mm0,mm1

psrlq       mm0,2

pand              mm0,0x3f3f3f3f3f3f3f3f

paddusb  mmx,mm0

③符號擴充套件指令:

mm0:*,*,a,b  =>  現在要符號擴充套件為 mm0:(a符號)a, (a符號)b

movq      mm1,mm0     

pcgtm    mm1,0                         //比較mm0,生成mm1:(a符號) (b符號)()()

punpcklwd     mm0,mm1

④分組指令

除了基本的分組指令以外,我們還可以利用移位指令和pand por指令來實現分組的功能,移位主要是要產生0,這樣por mm0,mm1就可以將mm0和mm1合併了。

比如:mm0(*,*,a,b) mm1(0,0,c,d)   則

psllq        mm0,32

por         mm0,mm1  => (a,b,c,d) 當然這個例子我們可以用普通的分組指令實現,但是在某些複雜的處理中,這樣的處理是必須的。

總之,要靈活運用mmx的現有指令來實現自己需要的功能。

v  mmx程式設計心得

使用mmx技術進行程式設計,目的就是要提高運算速度,所以,對於如何盡可能的提高**的效率,我們是要特別關注的。這裡,我介紹一些需要注意的事項。

① 盡可能的提高記憶體訪問的容量,我們可以看看下面的**:

for (j=0; j__asm

僅僅將幾個8位的寫,改為64位的寫,測試得到速度提公升了25%,同樣的道理,我們要盡可能的將幾個movq寫在一起,這樣可以提高5%左右的速度。原c**的效率也是很高的,它不用陣列的來定址,而是將s+= lx2; 從而將二維陣列的定址改為一維陣列的定址。盡可能的減少定址的複雜度,這也是一種高效的辦法。 還有一點就是如果將原來的簡單賦值改為memcpy()的話,可以提高大約10%的速度。這也是提高了資料流通容量的關係。

② 一些要注意的地方:

1.       盡可能的使用static變數, 訪問這樣的變數是很快的=訪問立即數的速度

2.       由於只有乙個mmx移位暫存器, (移位分組指令) 是不能配對的

3.       不要在eax使用完, 使用ax, 不要使用完乙個mm1,就立即使用它

4.       可以這樣立即使用mm1, movq  mm2,mm1  movq mm1,mm3 (z順序是可以的)

5.       (4個以上)movq盡可能的在一起, 前提是在一起的mov不要使用一樣的mmx暫存器

6.       mov eax, [esi] ([esi+2*eax]) 訪問定址的記憶體是特別的慢的

7.       同上 stow 也是很慢的 (mov cx,n;   loop是很慢的,如果可能,要展開迴圈)

8.       盡可能的在暫存器中完成操作,不要去訪問記憶體

9.       用變數名訪問變數,尤其是static的,是很快.

10.   訪問定址的記憶體的速度下降 》 資料不對齊8位的速度下降 》 指令不配對的速度下降

11.   所以在傳統的**優化的方法中,構造陣列,然後將運算變為查表的方法,有的時候在mmx技術內反而會降低速度。(這個時候,如果真的用查表有提公升速度的話,建議採用段位址+偏移量的辦法)

zencart開發文件

在zencart開發中,做乙個新的功能模組時,首先要明確這個功能的流程和與原來 的關聯。然後,需要為這個功能模組取乙個名稱標識,盡量不要與原有的模組名稱不相同。zencart模組結構 1.資料庫資料表部分 2.後台管理部分 3.前台功能顯示部分 資料庫部分 zencart使用mysql數庫據,在設計...

RxJava開發文件

在我們的第乙個列子裡,我們將檢索安裝的應用列表並填充recycleview的item來展示它們。我們也設想乙個下拉重新整理的功能和乙個進度條來告知使用者當前任務正在執行。首先,我們建立observable。我們需要乙個函式來檢索安裝的應用程式列表並把它提供給我們的觀察者。我們乙個接乙個的發射這些應用...

關於開發文件

軟體開發文件是乙個軟體的支柱,是軟體開發使用和維護過程中的必備資料。它能提高軟體開發的效率,保證軟體的質量,而且在軟體的使用過程中有指導,幫助,解惑的作用,尤其在維護工作中,文件是不可或缺的資料。軟體文件可以分為開發文件和產品文件兩大類。1.1 開發文件 功能要求 於客戶要求和市場調查,是軟體開發中...