青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

asm, c, c++ are my all
-- Core In Computer
posts - 139,  comments - 123,  trackbacks - 0
[轉]用SIMD指令優化程序之拋磚引玉

小談
CPU 緩存體系

  現在的 CPU 依舊采用馮諾伊曼體系,喜歡像傻子一樣從頭執行到尾,中途沒有任何的跳轉停頓等待??墒乾F實情況是,大部分程序里面還是少不了 IF ELSE 之類的判斷,循環就更加得多了。如何優化循環大家可以自己琢磨,其實不難,可以參考一下《高質量 C\C++ 編程指南》

  現在 CPU 上都有 Level 1 指令緩存(又叫做 L1 Trace )與 Level 1 數據緩存( L1 Data Cache )。 PMMX P2 , P3 為二者都準備了 16kb ,我的 P4 Northwood (以下簡稱 P4NW )有 8kbL1 數據緩存和 12kb 指令緩存。 CPU 讀取 L1 Data Cache 中的數據只需要 1 個時鐘周期,速度非???,應該是僅次于寄存器了。數據緩存是由 256 或者 512 32bytes 組成的,也就是 32bytes 對齊的,而 P4NW 64bytes 字節對齊的,并行 4 路,總共 128 行。當你處理的數據沒有載入緩存的時候, CPU 將從內存讀取緩存行大小的數據,所以緩存行總是對齊到能被 32 整除的物理地址。 CPU L1 數據緩存中的數據進行操作是最快速的。所以推薦內存地址最起碼是 32byte 對齊的。目前編譯器在這個地方的優化已經非常好了,一般都是 4byte 對齊,當然也都是 32 對齊的。在后面你將會看到, SSE2 要求數據是 16 字節對齊的。

?   緩存類似一個 C++ set 容器,但是不能賦值到一個任意的內存地址。每行本身都有 1 7bit 大小的關聯值( set value )要和目標內存地址的 5 11 位對應( 0-4 位已經忽略了),也可以理解為,關聯值是內存段地址的一部分。 PPro 中,有 128 個關聯值對應到 2 行,所以最多可以為任意的內存單元準備 2 個緩存行。 PMMX P2 P3 P4NW 4 個。由于內存是分段的,所以說 CPU 只能為, 5-11 位地址相同的內存準備 2 或者 4 個不同的緩存行。如何為兩個內存地址賦予相同的關聯值呢?把 2 個地址的低 5bit 去掉,這樣就能被 32 整除了。如果這 2 個截斷了的地址都是 4096 1000H )的倍數,那么這兩個地址就有了相同的關聯值。

?   讓我們用匯編加深一下印象,假設 ESI 中是 32 對齊的地址。

? ??????????????????????????????????????? AGAIN:? MOV? EAX,? [ESI]

MOV? EBX,? [ESI+13*4096+4]

MOV ?ECX,? [ESI+20*4096+28]

DEC? ?EDX

JNZ ??AGAIN

   Oh Year ,這里 3 個地址都有相同的關聯值,而且地址跨度都超過了數據緩存的大小,可這個循環在 PPro 上效率會相當低。當你想讀取 ECX 的值的時候,將沒有空閑的緩存行了 —— 因為共享一個關聯值,而且 2 行已經被使用了。此時 CPU 將騰出最近使用的 2 個緩存行,一個已經被 EAX 使用。然后 CPU 把這個緩存行用 [ESI+20*4096] [ESI+20*4096+31] 的內存數據填充,然后從緩存中讀取 ECX 。聽起來好象相當的煩瑣。更加糟糕的是,當又需要讀取 EAX 的時候,還需要重復上述的過程,需要對內存緩存來回操作,效率相當的低,甚至不如不用緩存??墒?,如果我們把第三行改成:

MOV? ECX,? [ESI+20*4096+32]

  哦,不好,看起來,我們的地址超過了 32 ,不能被整除了??墒沁@樣有了不同的關聯值,也就意味著有了 1 個新行,不再共享可憐的 2 個行。這樣一來,對三個寄存器的操作就不需要反復的用 2 個緩存行進行調度了,各有一個了。嘿嘿,這次只需要 3 個時鐘周期了,而上一個要 60 個周期。這是在 PPro 上的,在后來的 CPU 中都是 4 路的,也就不存在上面的問題了。搞笑的是, Intel 的文檔卻錯誤的說 P2 的緩存是 2 路的。雖然說很少人在用那么古老的 CPU ,可是其中的道理大家應該明白。

  可是判斷要訪問的部分數據是否有相同的關聯值,也就是關于緩存是否能夠命中的問題,是相當困難的,匯編還好,用高等級語言編譯過的程序鬼知道是否對緩存做過優化呢。所以么,推薦,在程序的核心部分,對性能要求最高的部分,先對齊數據,然后確保使用的單個數據塊不要超過緩存大小, 2 個數據塊,單個不要超過緩存大小的一半(仔細想想為什么,因為關聯值的問題,可以緩存分為兩部分處理兩塊)??墒谴蟛糠智闆r下,我們都是使用遠比數據緩存大的多的結構,以及編譯器自己返回的指針,然后為了優化你可能希望把所有頻繁使用的變量放到一個連續的數據塊中以充分利用緩存。我們可以這樣做,把靜態變量數值拷貝到棧中的局部變量中,等子函數或者循環結束后再拷貝回來。這樣一來就相當于把靜態變量放入了連續的地址空間中去。

當讀取的數據不在 L1 Cache 內時, CPU 將要從 L2 Cache 讀取 L1 緩存行大小的數據到 L1 里去,大概需要 200ns 的時間(也就是 100Mhz 系統的 20 個時鐘周期),但是直到你能夠使用這些數據前,又需要有 50-100ns 的延遲。最糟糕的是,如果數據也不在 L2 Cache 中,那么就只能從最慢速的內存里讀取了,內存的龜速哪能和全速的緩存相比。

好了,關于緩存的知識可以就此打住了,下面開始講如何優化緩存。無非就是 3 種方法,硬件預?。?/span> Prefetch )、軟件預取、使用緩存指令。關于預取的注意事項主要有這些:

<!--[if !supportLists]--> 1、? <!--[endif]--> 合理安排內存的數據,使用塊結構,提高緩存命中率。

<!--[if !supportLists]--> 2、? <!--[endif]--> 使用編譯器提供的預取指令。比如ICC中的_mm_prefetch _mm_stream,甚至_mm_load等比較“傳統”的指令。

<!--[if !supportLists]--> 3、? <!--[endif]--> 盡可能少的使用全局的變量或者指針。

<!--[if !supportLists]--> 4、? <!--[endif]--> 程序盡可能少的進行判斷跳轉循環。

<!--[if !supportLists]--> 5、? <!--[endif]--> 使用const標記,不要在代碼中混合register聲明。

不過要提醒一句,真正提高程序效率的方法不是那種,從頭到尾由于外科手術般的解剖,一個一個地方的優化,請抓住程序最核心的部分進行優化,記住 80-20 規則。

?

使用 SIMD

先復習一下對齊指令, __declspec(aliagn(#)) # 替換為字節數。比如想聲明一個 16 字結對齊的浮點數組, __declspec(aliagn(16)) float Array[128] 。需要注意的是,最好充分了解你 CPU 的類型,支持哪些指令集。 SIMD 主要使用在需要同時操作大量數據的工作領域,比如 3D 圖形處理(游戲),物理建模( CAD ),加密,以及科學計算領域。據我所知,目前 GPGPU 也是使用 SIMD 的代表之一。

MMX

主要特性: 57 條指令, 64bit FP 寄存器 MM0-MM7 ,對齊到 8 80bit FP 寄存器 ST0-ST7 。需要數據 8 字節對齊,也就是使用 Packed 數字。

PS :這里冒出了一個問題,為什么 Intel 要把 MMX 的寄存器和 FPU 的寄存器混合起來使用呢?因為這里牽涉到一個 FPU 狀態切換問題,后面會提到,當你在一段代碼中又要用到 MMX 指令又要用到傳統的 FPU 指令,那么需要保存 FPU 狀態,或者退出 MMX ??墒沁@種操作對于 FPU 來說非常昂貴,而且對于多任務操作系統來說,近乎于不可能完成的任務 —— 同時有許多程序,有些需要 MMX ,有些不需要,而正確地進行調度會變得非常困難。所以 Intel 將保存狀態的工作完全交給了 CPU 自己,軟件人員無須作太多這方面的工作,這樣一來,就向前向后兼容了多任務操作系統,比如 Windows Linux 。后來隨著操作系統和 CPU 的不斷升級,操作系統開發人員發布了一個補丁包,就可以讓操作系統使用新的寄存器。這時人們都發現 Intel 的這種做法是相當短視的,這可以當作一個重大的失誤。后來 Intel 通過引入了新的浮點指令集,這時才加入 XMM 寄存器??稍斐蛇@段故事的原因卻根本不是技術問題,保證兼容性也是一個方面,總之真的說不清楚。你只要記得無法同時使用 MMX FPU 就可以了, CPU 要進行模式切換。

SSE1

主要特性: 128bit FP 寄存器 XMM0-XMM7 。增加了數據預取指令。額外的 64bit 整數支持。支持同時處理 4 個單精度浮點數,也就是 C\C++ 里的 float 。

適用范圍:多媒體信號處理

SSE2

主要特性: 128bit FP 寄存器支持處理同時處理 2 個雙精度 double 浮點數,以及 16byte 8word 4dword 2quadword 整數。

適用范圍: 3D 處理 語音識別 視頻編碼解碼

SSE3

主要特性:增加支持非對稱 asymmetric 和水平 horizontal 計算的 SIMD 指令。為 SIMD 提供了一條特殊的寄存器 load 指令。線程同步指令。

適用范圍:科學計算 多線程程序

手頭工具

1 、選擇一個合適的編譯器,推薦用 Intel C++ Compiler (以下簡稱 ICC ),以及 Visual Studio .NET 2003 及以上 IDE 附帶的 C++ 編譯器。同時, Microsoft C++ Compiler 也支持 AMD 3DNow GCC C++ Compiler 沒有測試。

2 Intel 以及 AMD 的匯編指令集手冊。這個是必需的,強烈建議每個C++ Coder人手準備一份。

? 所有的都用 C++ 混合變成的方式實現

使用范例:

向量乘法在 3D 處理中非常非常多,多半用于計算單位矢量的夾角。

我們先定義一個頂點結構。

__declspec(align( 16 ))? struct ?Vertex{
????
float
?x,y,z,w;
};
??? 16字節對齊的結構,其實本身也是16字節的東西。如果沒有對齊,運行時會報錯。

w是其次坐標系的參數,處理向量的時候不需要用到。我的函數是這樣的:

float ?Dot(Vertex * ?v1,Vertex * ?v2)
{
????Vertex?tmp;
????__asm{
????????MOV?EAX,[v1];
????????MOVAPS?XMM0,[EAX];
????????MOV?EAX,[v2];
????????MOVAPS?XMM1,[EAX];
????????MULPS?XMM0,XMM1;
????????MOVAPS?tmp,XMM0;
????};
????
return ?tmp.x? + ?tmp.y? +
?tmp.z;
};

??? VC中反匯編之:
?1?float?Dot(Vertex*?v1,Vertex* ?v2)
?2?
{
?3?
0041C690??push????????ebx??
?4?
0041C691??mov?????????ebx,esp?
?5?0041C693??sub?????????esp,8
?
?6?
0041C696??and?????????esp,0FFFFFFF0h?
?7?0041C699??add?????????esp,4
?
?8?
0041C69C??push????????ebp??
?9?0041C69D??mov?????????ebp,dword?ptr?[ebx+4
]?
10?0041C6A0??mov?????????dword?ptr?[esp+4
],ebp?
11?
0041C6A4??mov?????????ebp,esp?
12?
0041C6A6??sub?????????esp,0E8h?
13?
0041C6AC??push????????esi??
14?
0041C6AD??push????????edi??
15?0041C6AE??lea?????????edi,[ebp-
0E8h]?
16?
0041C6B4??mov?????????ecx,3Ah?
17?
0041C6B9??mov?????????eax,0CCCCCCCCh?
18?
0041C6BE??rep?stos????dword?ptr?[edi]?
19?
????Vertex?tmp;
20?
????__asm{
21?
????????MOV?EAX,[v1];
22?
0041C6C0??mov?????????eax,dword?ptr?[v1]?
23?
????????MOVAPS?XMM0,[EAX];
24?
0041C6C3??movaps??????xmm0,xmmword?ptr?[eax]?
25?
????????MOV?EAX,[v2];
26?
0041C6C6??mov?????????eax,dword?ptr?[v2]?
27?
????????MOVAPS?XMM1,[EAX];
28?
0041C6C9??movaps??????xmm1,xmmword?ptr?[eax]?
29?
????????MULPS?XMM0,XMM1;
30?
0041C6CC??mulps???????xmm0,xmm1?
31?
????????MOVAPS?tmp,XMM0;
32?
0041C6CF??movaps??????xmmword?ptr?[tmp],xmm0?
33?
????};
34?????return?tmp.x?+?tmp.y?+
?tmp.z;
35?
0041C6D3??fld?????????dword?ptr?[tmp]?
36?0041C6D6??fadd????????dword?ptr?[ebp-
1Ch]?
37?0041C6D9??fadd????????dword?ptr?[ebp-
18h]?
38?};
??? 前面都是保護現場入Stack的代碼,沒有必要管。我之所以這樣,在Stack中聲明了一個零時變量返回之,是為了減少代碼的行數。有興趣地可以參考本文后面引用資料中的Intel范例,代碼多的多,功能卻一樣。這樣就可以利用SIMD計算點乘了。圖示:
??? 這種頂點格式稱為AoS(Array of structure),這種結構的好處是,能夠和現有的程序結構,比如D3D中的FVF頂點格式,和GL中的頂點格式。但是,由于許多情況下,并沒有使用第四各浮點數,這就讓SIMD指令浪費了25%的性能。于是有了SoA格式,讓我們重新來過。
??? 我借用了一下上面一個結構的指令,還是沒有用_mm_128格式,讓大家看得清楚一些:
__declspec(align( 16 ))? struct ?Vertex_soa{
?????
float ?x[ 4 ],y[ 4 ],z[ 4 ],w[ 4
];
};
??? 依舊16字節對齊。計算函數如下:
?1?void?Dot(Vertex_soa*?v1,Vertex*?v2,float* ?result)
?2?
{
?3?
????Vertex?tmp1,tmp2;
?4?
????__asm{
?5?
????????MOV?ECX,v1;
?6?
????????MOV?EDX,v2;
?7?

?8? ????????MOVAPS?XMM7,[ECX];
?9?????????MOVAPS?XMM6,[ECX+16
];
10?????????MOVAPS?XMM5,[ECX+32
];
11?????????MOVAPS?XMM4,[ECX+48
];
12?
????????MOVAPS?XMM0,XMM7;
13?
????????UNPCKLPS?XMM7,XMM6;
14?
????????MOVLPS?[EDX],XMM7;
15?????????MOVHPS?[EDX+16
],XMM7;
16?
????????UNPCKHPS?XMM0,XMM6;
17?????????MOVLPS?[EDX+32
],XMM0;
18?????????MOVHPS?[EDX+48
],XMM0;
19?

20? ????????MOVAPS?XMM0,XMM5;
21?
????????UNPCKLPS?XMM5,XMM4;
22?
????????UNPCKHPS?XMM0,XMM4;
23?????????MOVLPS?[EDX+8
],XMM5;
24?????????MOVHPS?[EDX+24
],XMM5;
25?????????MOVLPS?[EDX+40
],XMM0;
26?????????MOVHPS?[EDX+56
],XMM0;
27?

28? ????????MOVAPS?XMM3,[EDX];
29?????????MOVAPS?XMM2,[EDX+16
];
30?????????MOVAPS?XMM1,[EDX+32
];
31?????????MOVAPS?XMM0,[EDX+48
];
32?

33? ????????MULPS?XMM3,XMM2;
34?
????????MULPS?XMM1,XMM0;
35?
????????MOVAPS?tmp2,XMM1;
36?
????????MOVAPS?tmp1,XMM3;
37?
????};
38?????result[0]?=?tmp1.x?+?tmp1.y?+
?tmp1.z;
39?????result[1]?=?tmp2.x?+?tmp2.y?+
?tmp2.z;
40?};
??? Oh Year,就是這樣了,同時計算了1對乘法。我在代碼中借用了一下前面的頂點結構,這樣方便一些。至于SOA格式,請看前面的聲明。很多代碼都是轉換Stack中的內存格式,轉換成AOS格式,這樣才能使用SIMD指令計算。

??? 通過上面的演示,想必大家已經對SIMD有了個直觀地認識,其實在自己的代碼中加入這些是非常方便與容易的。雖然說現在的CPU性能已經提高了許多,性能也強了許多,可是在諸多對性能要求高的地方,還是非??緹煶绦騿T的水平的。
posted on 2006-08-24 21:00 Jerry Cat 閱讀(641) 評論(0)  編輯 收藏 引用

<2007年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(7)

隨筆檔案

最新隨筆

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲深夜激情| 亚洲成在人线av| 久久久久久久综合色一本| 男人的天堂成人在线| 亚洲国产日韩综合一区| 欧美成人一二三| 久久九九久久九九| 国产精品久久久久久户外露出| 99热这里只有精品8| 91久久精品国产91久久性色| 9久草视频在线视频精品| 尤物九九久久国产精品的分类| 欧美精品在线免费播放| 欧美激情乱人伦| 欧美中文日韩| 欧美激情网友自拍| 亚洲综合久久久久| 玖玖玖国产精品| 99国产精品视频免费观看一公开| 国产精品成人一区| 欧美午夜精品久久久久免费视 | 欧美亚洲网站| 欧美一区二区精品在线| 欧美成年视频| 亚洲一区二区免费在线| 亚洲自拍偷拍网址| 午夜精品久久久久久久久久久| 妖精视频成人观看www| 噜噜噜噜噜久久久久久91| 亚洲精品一区二区三区福利| 欧美成人资源| 亚洲激情第一区| av成人老司机| 久久久久综合网| 欧美私人网站| 日韩视频免费在线观看| 噜噜噜久久亚洲精品国产品小说| 国产午夜精品在线| 欧美福利一区二区| 亚洲人体1000| 欧美一区二区免费观在线| 你懂的网址国产 欧美| 亚洲九九九在线观看| 亚洲综合色网站| 99视频一区二区| 亚洲精一区二区三区| 欧美国产第一页| 欧美激情按摩| 国产性猛交xxxx免费看久久| 一本大道久久a久久精品综合 | 欧美在线观看视频一区二区三区| 欧美精品在线网站| 国内自拍视频一区二区三区| 在线中文字幕一区| 亚洲男女毛片无遮挡| 久久中文字幕一区| 国产一区在线视频| 午夜一区二区三区在线观看| 国产精品久久国产愉拍| 久久青草欧美一区二区三区| 国产无一区二区| 国产亚洲在线| 亚洲欧美视频一区| 国产精品99久久久久久www| 欧美日韩你懂的| 亚洲视频日本| 欧美亚洲专区| 欧美精品一区在线播放| 日韩亚洲在线| 欧美成人精品1314www| 女主播福利一区| 日韩写真在线| 久久精品视频在线免费观看| 久久疯狂做爰流白浆xx| 91久久国产综合久久| 国内在线观看一区二区三区 | 亚洲一区二区三区精品视频| 亚洲理论在线观看| 国产精品第一区| 免费在线观看成人av| 性欧美精品高清| 欧美不卡视频一区| 欧美一区成人| 久久一区二区三区四区| 久久久久久久综合| 亚洲福利一区| 欧美日韩亚洲国产一区| 欧美自拍偷拍午夜视频| 欧美成人精品一区二区三区| 欧美一区二区性| 欧美插天视频在线播放| 久久久精品网| 日韩视频不卡中文| 久久精品视频在线| 欧美日本不卡高清| 麻豆av福利av久久av| 欧美一区午夜精品| 久久免费视频网站| 久久精品亚洲| 亚洲国产三级网| 你懂的国产精品| 亚洲图色在线| 亚洲人www| 激情欧美一区二区| 在线亚洲一区| 欧美午夜不卡影院在线观看完整版免费| 欧美午夜精品理论片a级按摩| 99视频国产精品免费观看| 亚洲天堂免费观看| 一本一本久久a久久精品综合妖精| 欧美区一区二| 欧美99在线视频观看| 亚洲高清三级视频| 国产精品天美传媒入口| 亚洲乱亚洲高清| 蜜桃伊人久久| 欧美在线高清| 欧美一区二区视频免费观看| 一区二区三区精品久久久| 免费视频一区| 久久gogo国模裸体人体| 韩日午夜在线资源一区二区| 免费一级欧美在线大片| 国产精品久久久久99| 国产精品99久久久久久人| 久久婷婷一区| 欧美一区二区视频在线| 一区二区三区毛片| 99精品国产在热久久婷婷| 在线日韩欧美| 欧美精品电影| 另类av一区二区| 亚洲永久网站| 久久理论片午夜琪琪电影网| 国产精品草草| 国产精品成人一区二区三区夜夜夜 | 日韩性生活视频| 亚洲黄色成人久久久| 亚洲免费精彩视频| 久久久久国产一区二区三区四区| 亚洲欧美日韩精品在线| 久热精品视频在线| 美女亚洲精品| av成人黄色| 欧美午夜精品久久久久久浪潮| 欧美女激情福利| 欧美中文字幕| 久久大逼视频| 亚洲精品视频一区二区三区| 先锋影音国产一区| 激情欧美日韩一区| 亚洲女同在线| 久久久久久久久久久成人| 久久综合狠狠| 欧美日本一区二区视频在线观看| 狠狠色伊人亚洲综合成人| 欧美日韩另类综合| 欧美亚男人的天堂| 亚洲国产mv| 午夜精品久久久久久久久久久| 欧美系列亚洲系列| 好吊视频一区二区三区四区| 一区二区在线视频| 亚洲视频一区在线| 久久手机免费观看| 麻豆成人在线观看| 日韩天堂在线视频| 亚洲一区二区三区乱码aⅴ| 男人的天堂亚洲| 亚洲二区在线视频| 亚洲国产另类 国产精品国产免费| 亚洲伊人第一页| 午夜精品久久久| 国产精品精品视频| 一区二区三区精品视频| 午夜精品一区二区三区在线视| 国产精品揄拍500视频| 久久精品在线| 日韩一级裸体免费视频| 欧美福利视频| 亚洲色图制服丝袜| 亚洲精品欧美日韩专区| 一本一本大道香蕉久在线精品| 国产欧美一区二区三区视频| 久久视频免费观看| 欧美在线亚洲一区| 久久久久久亚洲精品中文字幕| 在线观看av不卡| 亚洲三级视频| 亚洲人成免费| 亚洲国产婷婷综合在线精品| 日韩系列在线| 欧美一区二区三区免费视频| 伊人男人综合视频网| 亚洲欧美卡通另类91av| 国产色产综合色产在线视频| 美女任你摸久久| 国产精品久久久久久久午夜| 蜜臀a∨国产成人精品| 国产精品久久久久久亚洲毛片|