向量化的方法.doc_第1頁(yè)
向量化的方法.doc_第2頁(yè)
向量化的方法.doc_第3頁(yè)
向量化的方法.doc_第4頁(yè)
向量化的方法.doc_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

使用英特爾編譯器進(jìn)行自動(dòng)向量化 作者:Yang Wang (Intel)自動(dòng)向量化是英特爾編譯器提供的一個(gè)可以自動(dòng)的使用SIMD指示的功能。 在處理數(shù)據(jù)時(shí), 編譯器自動(dòng)選擇MMX, Intel Streaming SIMD 擴(kuò)展(Intel SSE, SSE2, SSE3 和SSE4)等指令集, 對(duì)數(shù)據(jù)進(jìn)行并行的處理。 使用編譯器提供的自動(dòng)向量化功能是提高程序性能的一個(gè)非常有效的手段。自動(dòng)向量化在IA-32和Intel 64的平臺(tái)上均提供很好的支持。英特爾編譯器提供的自動(dòng)向量化相關(guān)的編譯選項(xiàng)如下所示。”/Q”開頭的選項(xiàng)是針對(duì)Windows平臺(tái)的, “-“開頭的選項(xiàng)是針對(duì)Linux*和Mac平臺(tái)的。-x, /Qx按照該選項(xiàng)指定的處理器類型生成相應(yīng)的優(yōu)化代碼。 比如-xSSE3, 該選項(xiàng)指定編譯器生成Intel SSE3指令的代碼。 又比如-xSSE3_ATOM, 該選項(xiàng)針對(duì)Intel Atom 處理器進(jìn)行優(yōu)化。-ax, /Qax如果指定該選項(xiàng), 在生成的單一目標(biāo)文件中, 不但會(huì)生成專門針對(duì)指定的處理器類型進(jìn)行優(yōu)化的代碼, 同時(shí)也生成通用的IA-32架構(gòu)的代碼。 該選項(xiàng)主要是為了生成代碼的兼容性考慮。-vec, /Qvec打開或者關(guān)閉編譯器的向量化優(yōu)化。 默認(rèn)情況下自動(dòng)向量化是打開的。-vec-report, /Qvec-report該選項(xiàng)用戶控制在編譯過(guò)程中產(chǎn)生的向量化消息報(bào)告。編譯器提供的自動(dòng)向量化優(yōu)化默認(rèn)情況下是打開的。 在編譯過(guò)程中我們可以使用-vec-report選項(xiàng)來(lái)打開向量化診斷消息報(bào)告。 這樣編譯器可以告訴我們有哪些循環(huán)被向量化了, 有哪些循環(huán)沒有被向量化已經(jīng)無(wú)法向量化的原因。在編譯程序的過(guò)程中, 有時(shí)候我們會(huì)發(fā)現(xiàn)編譯器報(bào)告說(shuō)某個(gè)循環(huán)無(wú)法被向量化。 很多時(shí)候無(wú)法向量化的原因都是因?yàn)檠h(huán)中存在的變量依賴關(guān)系。 有時(shí)候我們可以修改程序來(lái)消除這種依賴關(guān)系,有的時(shí)候我們可以使用編譯器提供的一些編譯指示來(lái)顯示的告訴編譯器如何處理這種依賴關(guān)系。 即使在某個(gè)循環(huán)已經(jīng)可以被自動(dòng)向量化的時(shí)候, 使用編譯器提供的對(duì)向量化的語(yǔ)言支持和編譯指示還可以提高編譯器向量化的效率, 提高程序執(zhí)行的性能。下面我們來(lái)詳細(xì)解釋一下編譯器提供的編譯指示以及這些指示對(duì)編譯器編譯的影響。在Intel編譯器中, 我們提供下面這樣一些對(duì)自動(dòng)向量化的語(yǔ)言支持和編譯指示。_declspec(align(n)指導(dǎo)編譯器將變量按照n字節(jié)對(duì)齊_declspec(align(n,off)指導(dǎo)編譯器將變量按照n字節(jié)再加上off字節(jié)的編譯量進(jìn)行對(duì)齊restrict消除別名分析中的二義性_assume_aligned(a,n)當(dāng)編譯器無(wú)法獲取對(duì)齊信息時(shí),假定數(shù)組a已經(jīng)按照n字節(jié)對(duì)齊#pragma ivdep提示編譯器忽略可能存在的向量依賴關(guān)系#pragma vector aligned|unaligned|always指定向量化的方式#pragma novector指定不做向量化下面我們就這些編譯指示做一些詳細(xì)的了解。 _declspec(align(n)首先我們來(lái)看看如何使用_declspec(align(n)來(lái)進(jìn)行自動(dòng)向量化。該指示主要是用來(lái)告訴編譯器一個(gè)變量的對(duì)齊方式。 當(dāng)一個(gè)變量的對(duì)齊方式為16字節(jié)對(duì)齊時(shí), 生成的向量化指令是最高效的。 當(dāng)編譯器不知道一個(gè)變量的對(duì)齊方式的時(shí)候, 他可能沒有辦法對(duì)該變量的使用進(jìn)行向量化, 或者編譯器會(huì)不得不生成條件語(yǔ)句來(lái)進(jìn)行有條件的向量化。 我們來(lái)看一下下面這個(gè)例子。File: vec1.cchar a;void vec1(void)int i;for(i=0;i1024;i+)ai = 1;使用下面命令編譯該程序:icl vec1.c -O2 -c /Qvec-report:3這時(shí)編譯器輸出:vec1.cvec1.c(10) (col. 2): remark: LOOP WAS VECTORIZED.我們可以看到編譯器對(duì)上面這個(gè)程序進(jìn)行了自動(dòng)向量化。 但是實(shí)際上, 由于編譯器不知道a的對(duì)齊字節(jié)數(shù), 所以他對(duì)變量a數(shù)據(jù)進(jìn)行了一些條件處理。 我們可以在編譯的時(shí)候加上-S選項(xiàng)來(lái)查看編譯器生成的匯編代碼。 實(shí)際上, 編譯器對(duì)該程序做了如下處理:temp = a&0x0f;if(temp != 0)temp = 16-temp;for(i=0;itemp;i+) ai = 1;/*下面是對(duì)齊的訪問*/for(i=temp;i1024;i+) ai = 1;如果我們指定了a的對(duì)齊方式, 比如我們使用_declspec(align(16)來(lái)定義變量a, 如下所示:_declspec(align(16) char a;void vec1(void)int i;for(i=0;i1024;i+)ai = 1;對(duì)于上面這段程序, 編譯器做了自動(dòng)向量化。 如果我們檢查生成的匯編代碼可以發(fā)現(xiàn),對(duì)于a的對(duì)齊方式的條件處理代碼已經(jīng)不見了。正確使用_declspec(align(n)以及其他align相關(guān)編譯指示可以幫助編譯器進(jìn)行自動(dòng)向量化以及提高編譯器自動(dòng)向量化的效率。 restrict使用restrict關(guān)鍵字可以顯式的告訴編譯器取消指針之間的二義性。 我們還是用下面這個(gè)例子來(lái)說(shuō)明restrict的使用。File: vec2.cvoid vec2(char* a, char* b, int n)int i;for(i=0;in;i+)ai = bi;使用以下命令進(jìn)行編譯:icl vec2.c -O2 -c /Qvec-report:3編譯器輸出:vec2.crestrict.c(5) (col. 2): remark: LOOP WAS VECTORIZED.restrict.c(5) (col. 2): remark: loop skipped: multiversioned.此時(shí)編譯器輸出multiversioned向量化代碼, 對(duì)同一個(gè)循環(huán)產(chǎn)生了多個(gè)版本的實(shí)現(xiàn)。實(shí)際上編譯器對(duì)代碼進(jìn)行了條件處理, 如下所示:void vec2(char* a, char* b, int n)int i;if(a+nb | b+na)for(i=0;in;i+) ai = bi; /*向量化循環(huán)*/elsefor(i=0;in;i+) ai = bi; /*串行循環(huán)*/可以看出,由于編譯器不知道指針a 和b之間是否存在重疊, 所以他對(duì)循環(huán)進(jìn)行了條件處理。 如果我們從語(yǔ)義上能夠保證a和b是不會(huì)發(fā)生重疊的, 那么我們就可以使用restrict關(guān)鍵字來(lái)顯式的告訴編譯器這一點(diǎn)。void vec2(char* restrict a, char* restrict b, int n)int i;for(i=0;in;i+)ai = bi;此時(shí)編譯器輸出沒有multiversioned。restrict.crestrict.c(5) (col. 2): remark: LOOP WAS VECTORIZED.注意C90里面不支持restrict關(guān)鍵字, 在windows平臺(tái)編譯的時(shí)候我們需要加上選項(xiàng)/Qrestrict來(lái)讓編譯器認(rèn)識(shí)restrict關(guān)鍵字。 #pragma vector使用#pragma vector編譯指示來(lái)顯式告訴編譯器使用某種方式來(lái)進(jìn)行自動(dòng)向量化。 比如在下面這個(gè)例子中, 我們可以保證變量a的地址是16字節(jié)對(duì)齊的,那么我們就可以使用#pragma vector aligned來(lái)顯式的告訴編譯器不需要考慮非對(duì)齊的情況。這樣產(chǎn)生的向量化代碼是最高效的。File: vec3.c#include void vec3(void)int i;char* a=_aligned_malloc(1024, 16);#pragma vector alignedfor(i=0;i1024;i+)ai = 1;在上面這個(gè)例子中, 如果我們不加上#pragma vector aligned, 編譯器會(huì)對(duì)循環(huán)進(jìn)行條件處理后的向量化。 大家可以對(duì)比一下兩種情況下生成的匯編代碼的區(qū)別。請(qǐng)注意我們?cè)谑褂?pragma vector aligned的時(shí)候需要保證被處理變量的對(duì)齊方式是16字節(jié)對(duì)齊的, 否則在使用了該編譯指示后可能會(huì)產(chǎn)生錯(cuò)誤的結(jié)果。在上面這個(gè)例子中, 我們稍作如下修改:#include void vec3(void)int i;char* a=_aligned_malloc(1024, 16);char* b = a+1;#pragma vector alignedfor(i=0;i1023;i+)bi = 1;循環(huán)中的b的地址不是16字節(jié)對(duì)齊的, 但是如果我們還是按照aligned的方式來(lái)做向量化, 產(chǎn)生的結(jié)果是編譯出來(lái)的可執(zhí)行程序運(yùn)行時(shí)異常。 在上面的例子中, 我們需要使用#pragma vector unaligned 編譯指示來(lái)正確的引導(dǎo)編譯器。 #pragma ivdep使用#pragma ivdep顯式的告訴編譯器忽略向量之間可能存在的依賴關(guān)系。參考下面這個(gè)例子。File: vec4.cvoid vec4(int* a, unsigned int n, unsigned int m)int i;for(i=0;in;i+)ai = ai+m;使用編譯器編譯該程序:icl vec4.c O2 -c /Qvec-report:3編譯器輸出:vec4.cvec4.c(6) (col. 2): remark: loop was not vectorized: existence ofvector dependence.vec4.c(7) (col. 3): remark: vector dependence: assumed ANTI dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed ANTI dependence between a line 7 and a line 7.如果我們可以保證a0到an-1和am到am+n-1之間不存在重疊, 那么我們就可以使用#pragma ivdep來(lái)顯式的告訴編譯器可以忽略ai和ai+m之間的依賴關(guān)系, 修改程序如下:void vec4(int* a, unsigned int n, unsigned int m)int i;#pragma ivdepfor(i=0;i Compiler Options. Many library routines that are part of Intel Compiler are more highly optimized for Intel microprocessors than for other microprocessors. While the compilers and libraries in Intel Compiler offer optimizations for both Intel and Intel-compatible microprocessors, depending on the options you select, your code and other factors, you likely will get extra performance on Intel microprocessors.While the paragraph above describes the basic optimization approach for Intel Compiler, with respect to Intels compilers and associated libraries as a whole, Intel Compiler may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include Intel Streaming SIMD Extensions 2 (Intel SSE2), Intel Streaming SIMD Extensions 3 (Intel SSE3), and Supplemental Streaming SIMD Extensions 3 (Intel SSSE3) instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors.Intel recommends that you evaluate other compilers to determine which best meet your requirements.使用#pragma simd進(jìn)行自動(dòng)向量化#pragma simd該編譯指示(SIMD)是12.0編譯器最新提供的功能。他可以強(qiáng)制性的讓編譯器做自動(dòng)并行化。 對(duì)于其他編譯指示比如#pragma ivdep來(lái)說(shuō), 如果編譯器編譯時(shí)發(fā)現(xiàn)用戶提供的編譯指示條件不滿足, 那么編譯器是不會(huì)根據(jù)編譯指示來(lái)進(jìn)行自動(dòng)向量化的。也就是說(shuō), 編譯器實(shí)際上還是會(huì)進(jìn)行編譯時(shí)的依賴關(guān)系檢查。 而對(duì)于#pargam simd來(lái)說(shuō), 無(wú)論編譯時(shí)條件如何, 編譯器總是會(huì)進(jìn)行自動(dòng)向量化。這種情況下, 用戶需要自己去保證被向量化的循環(huán)上語(yǔ)義的正確性, 需要自己保證被向量化變量之間的依賴關(guān)系的正確性。我們用一個(gè)例子來(lái)說(shuō)明編譯器的行為區(qū)別。File vec5.cvoid vec5(int* a, int n)int i;for(i=0;in;i+)ai = ai-1;對(duì)上面這個(gè)例子, 由于存在flow-dependence關(guān)系, 程序中的循環(huán)明顯是不能被向量化的。vec5.cC:testvec5.c(6) (col. 2): remark: loop was not vectorized: existence of vector dependence.C:testvec5.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.此時(shí)我們加上#pragma ivdep想讓編譯器忽略循環(huán)之間的依賴關(guān)系(當(dāng)然這種操作是不符合原始語(yǔ)義的)。void vec5(int* a, int n)int i;#pragma ivdepfor(i=0;in;i+)ai = ai-1;這時(shí)編譯該程序, 程序的輸出與不加#pragma ivdep時(shí)相同。 編譯器在進(jìn)行編譯的時(shí)候檢查發(fā)現(xiàn)了循環(huán)之間不可避免的依賴關(guān)系, 即使有#pragma ivdep存在, 編譯器也還是不會(huì)對(duì)該循環(huán)進(jìn)行向量化。如果我們加上#pragma simd, 重新編譯程序:void vec5(int* a, int n)int i;#pragma simdfor(i=0;in;i+)ai = ai-1;這時(shí)編譯輸出:vec5.cC:testvec5.c(6) (col. 2): remark: SIMD LOOP WAS VECTORIZED.程序中的循環(huán)被向量化了, 但是此時(shí)我們顯然不會(huì)得到一個(gè)正確的結(jié)果。我們?cè)倏匆粋€(gè)用SIMD的正確的例子。 比如下面這個(gè)程序:void vec5(int* a, int n, int m)int i;for(i=0;in;i+)ai = ai-m;編譯該程序: icl /O2 /c /Qvec_report:3, 編譯器會(huì)報(bào)告該程序因?yàn)榇嬖谙蛄恳蕾囮P(guān)系而不能被向量化。在該程序中, 如果我們可以保證m大于等于4, 那么我們可以加入#pragma simd指示如下所示:void vec5(int* a, int n, int m)int i;#prgama simdfor(i=0;i Compiler Options. Many library routines that are part of Intel Compiler are more highly optimized for Intel microprocessors than for other microprocessors. While the compilers and libraries in Intel Compiler offer optimizations for both Intel and Intel-compatible microprocessors, depending on the options you select, your code and other factors, you likely will get extra performance on Intel microprocessors.While the paragraph above describes t

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論