《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 設計應用 > 基于CUDA架構矩陣乘法的研究
基于CUDA架構矩陣乘法的研究
來源:微型機與應用2011年第24期
馬夢琦,劉 羽,曾勝田
(桂林理工大學 信息科學與工程學院,廣西 桂林541004)
摘要: 首先介紹了CUDA架構特點,在GPU上基于CUDA使用兩種方法實現了矩陣乘法,并根據CUDA特有的軟硬件架構對矩陣乘法進行了優化。然后計算GPU峰值比并進行了分析。實驗結果表明,基于CUDA的矩陣乘法相對于CPU矩陣乘法獲得了很高的加速比,最高加速比達到1 079.64。GPU浮點運算能力得到有效利用,峰值比最高達到30.85%。
Abstract:
Key words :

摘  要: 首先介紹了CUDA架構特點,在GPU上基于CUDA使用兩種方法實現了矩陣乘法,并根據CUDA特有的軟硬件架構對矩陣乘法進行了優化。然后計算GPU峰值比并進行了分析。實驗結果表明,基于CUDA的矩陣乘法相對于CPU矩陣乘法獲得了很高的加速比,最高加速比達到1 079.64。GPU浮點運算能力得到有效利用,峰值比最高達到30.85%。
關鍵詞: CUDA;矩陣乘法;加速比;峰值比

    隨著多核CPU和眾核GPU的快速發展,計算行業正在從只使用CPU的“中央處理”向CPU與GPU并用的“協同處理”發展,并行系統已成為主流處理器芯片。傳統的GPU架構受其硬件架構的影響不能有效利用其資源進行通用計算,NVIDIA(英偉達)公司推出的統一計算設備架構CUDA(Compute Unified Device Architecturem),使得GPU具備更強的可編程性,更精確和更高的性能,應用領域也更加廣泛。
    矩陣乘法是一種大計算量的算法,也是很耗時的運算。CPU提高單個核心性能的主要手段比如提高處理器工作頻率及增加指令級并行都遇到了瓶頸,當遇到運算量大的計算,CPU進行大矩陣的乘法就變得相當耗時,運算效率很低下。因此,GPU憑借其超強計算能力應運而生,讓個人PC擁有了大型計算機才具備的運算能力。本文運用GPU的超強計算能力在CUDA架構上實現了大矩陣乘法。
1 CUDA架構
    NVIDIA及時推出CUDA這一編程模型,在應用程序中充分結合利用CPU和GPU各自的優點,特別是GPU強大的浮點計算能力。CPU主要專注于數據高速緩存(cache)和流處理(flow control),而GPU更多地專注于計算密集型和高度并行的計算。盡管GPU的運行頻率低于CPU,但GPU憑著更多的執行單元數量使其在浮點計算能力上獲得較大優勢[1]。當前的NVIDIA GPU中包含完整前端的流多處理器(SM),每個SM可以看成一個包含8個1D流處理器(SP)的SIMD處理器。主流GPU的性能可以達到同期主流CPU性能的10倍左右。圖1所示為GPU與CPU峰值浮點計算能力的比較。

    CUDA的編程模型是CPU與GPU協同工作,CPU作為主機(Host)主要負責邏輯性強的事務處理及串行計算,GPU作為協處理器或者設備(Device)負責密集型的大規模數據并行計算。一個完整的CUDA程序=CPU串行處理+GPU Kernel函數并行處理。
    一個CUDA架構下的程序分為兩個部分,即上述的Host端和Device端。通常情況下程序的執行順序如下:Host端程序先在CPU上準備數據,然后把數據復制到顯存中,再由GPU執行Device端程序來處理這些數據,最后Host端程序再把結束運算后的數據從顯存中取回。
    圖2為CUDA編程模型,從中可以看出,Thread是GPU執行運算時的最小單位。也就是說,一個Kernel以線程網格Grid的形式組織,每個Grid由若干個線程塊Block組成,而每個線程塊又由若干個線程Thread組成。一個Kernel函數中會存在兩個層次的并行,Grid中Block之間的并行和Block中Thread之間的并行,這樣的設計克服了傳統GPGPU不能實現線程間通信的缺點[2]。

    同一個Block下的Thread共用相同的共享存儲器,通過共享存儲器交換數據,并通過柵欄同步保證線程間能夠正確地共享數據。因此,一個Block下的Thread雖然是并行的,但在同一時刻執行的指令并不一定都相同,實現了不同Thread間的協同合作。這一特性可以顯著提高程序的執行效率,并大大拓展GPU的適用范圍。
2 基于CUDA架構矩陣乘法的實現
2.1 一維帶狀劃分

    給定一個M×K的矩陣A和一個K×N的矩陣B,將矩陣B乘以矩陣A的結果存儲在一個M×N的矩陣C中。此種矩陣乘法使用了一維帶狀劃分,每個線程將負責讀取矩陣A中的一行和B中的一列,矩陣進行乘法運算并將計算結果存儲在全局存儲器。
    全局存儲器會對矩陣A進行N次讀取,對矩陣B進行M次讀取。假設數組在每個維度上的尺寸都是BLOCK_SIZE的整數倍。若矩陣大小為32×32,則可表示為(2×16)×(2×16)。下面的內核定義中,結果矩陣C中的每個元素由一個線程負責,for()循環完成A中第X行與B中第X列對應元素的乘加運算,并將結果累加到Cvalue。
      For( int e=0;e < A.width;++e)
      Cvalue+=A.elements[row*A.width+e] *
B.elements[e*B.width+col];
      C.elements[row*width+col]=Cvalue;
      在矩陣相乘實現中,這個內核運算的速度不盡人意,主要瓶頸在于對內存的重復讀取,計算量是2×M×N×K flop,而全局內存的訪問量為2×M×N×K B[3]。若矩陣維數為1 024×1 024,則此次矩陣相乘的計算量就有2 G flop,當矩陣維數更大時,這個運算量就相當大,在內存的讀取上會浪費大量的時間。
2.2 二維棋盤劃分
    因為矩陣A的行和矩陣B的列多次被讀取,為了避免重復加載,選擇把矩陣進行分塊運算,使用shared memory來實現矩陣乘法。運用shared memory的好處在于其延遲小于global memory,并且還能使線程間進行通信。矩陣A只被讀了N/BLOCK_SIZE次,矩陣B僅被讀了M/BLOCK_SIZE次,節省了大量的global memory帶寬。
    首先把劃分的小矩陣塊加載到share memory,則小矩陣本身的乘法就不用去存取外部的任何內存了,因此在二維棋盤劃分中,矩陣乘法的計算量仍然是2×M×N×K flop,b是矩陣B劃分的小矩陣塊的大小,則全局內存訪問量是2×M×N×K/b B。
    棋盤劃分運算可以表示為:C矩陣的(0,0)~(15,15)=A(0~15,0~15)×B(0~15,0~15)+A(0~15,16~31)×B(16~31,0~15)+A(0~15,32~47)×B(32~47,0~15)+…+A(0~15,(16×(n-1)-1)~(16×(n-1))×B((16×(n-1)-1)~(16×(n-1)),0~15)。
        for (int j=0;j<wA;j+=BLOCK_SIZE)
    {    //聲明用于存儲A,B子塊的share memory數組
        __shared__ float As[BLOCK_SIZE][BLOCK_SIZE];
        __shared__ float Bs[BLOCK_SIZE][BLOCK_SIZE];
        }...
        //兩個子塊的乘加,每個線程負責C中一個元素
值的計算
        for (int k = 0; k < BLOCK_SIZE; ++k)
        {
           float t;
           C sub + = As [ ty ] [ k ] * Bs [ k ] [ tx ];
           Cs [ ty ] [ tx ] = C sub;
        }
    __syncthreads();
    ....
    C[(by*BLOCK_SIZE+ty)*wA+bx*BLOCK_SIZE+tx] = Csub;
    dim3 myblock(BLOCK_SIZE,BLOCK_SIZE,1);
    dim3mygrid(((wB+BLOCK_SIZE-1)/BLOCK_SIZE),
(wB+BLOCK_SIZE-1)/BLOCK_SIZE,1);
    根據NVIDIA CUDA Programming Guide,一個Block 里至少要有64個Thread,最多有512個Thread。官方建議256個Thread是最合適的,因為此時有足夠多的active warp有效地隱藏延遲,使得SM能夠盡量滿負荷工作[4]。為便于理解,假設矩陣為n×n ,此時BLOCK_SIZE設置為16,使用dim3來設計,每個Block包含16×16個Thread,一個Grid共有(n/16)×(n/16)個Block。
    BLOCK_SIZE是不是越大越好呢?這樣一個SM里的Thread 就更多,雖然Thread越多越能隱藏 latency,但G80/G92架構每個SM上shared memory僅有16 KB,這會讓每個Thread 能使用的資源更少,效率反而會下降。
2.3 根據CUDA架構對矩陣乘法進行優化

 


    因為棋盤劃分中涉及到的是二維數組,cudaMalloc2D()能確保分配二維數組并且能分配適當的填充以滿足對齊要求,還能確保在訪問行地址或者二維數組與其他設備內存之間的數據復制能達到最佳性能。
    二維棋盤劃分方法僅限于數組大小必須是BLOCK_SIZE的整數倍,若矩陣維數并不是16的整數倍,則會造成運算效率的下降,此時可以利用CUDA架構特點和CUDA提供的cudaMallocPitch()函數來解決此問題。cudaMallocPitch()可以自動地以最佳倍數來分配內存。
    呼叫Kernel部分需要修改成:
    matrixMul<<<mygrid,myblock>>>(d_A,d_B,d_C,wA,wB,
d_pitchA/sizeof(float),d_pitchB/siz
eof(float),d_pitchC/sizeof(float));
    cudaMalloc部分改成:
      float* d_A;
cutilSafeCall(cudaMallocPitch((void**)&d_A,&d_pitchA,
wA*sizeof(float),wB));
      float* d_B;
cutilSafeCall(cudaMallocPitch((void**)&d_B,&d_pitchB,
wB*sizeof(float),wA));
      float* d_C;
cutilSafeCall(cudaMallocPitch((void**)&d_C,&d_pitchC,
wB*sizeof(float),wB));
    矩陣內存與顯存之間的讀取都需要做相應的修改:    
cutilSafeCall(cudaMemcpy2D(d_A,d_pitchA,A,wA*sizeof(float),
wA*siz
eof(float),wB,cudaMemcpyHostToDevice));    
cutilSafeCall(cudaMemcpy2D(d_B,d_pitchB,B,wB*sizeof(float),
wB*sizeof(float),wA,cudaMemcpyHostToDevice));
cutilSafeCall(cudaMemcpy2D(C,wB*sizeof(float),d_C,d_pitchC,
wB*sizeof(float),wB,cudaMemcpyDeviceToHost));
    在數值分析,Kahan求和算法(也稱作補償總和)能顯著減少浮點數運算的誤差,在CUDA矩陣乘法中可以通過使用Kahan求和算法來提高計算精準度[5]。算法如下:
    for (int k = 0; k < BLOCK_DIM; ++k)
    {
            float t;
        comp -= AS[ty][k] * BS[k][tx];
        t = Csub - comp;
        comp = (t - Csub) + comp;
        Csub = t;
    }
3 測試環境及實驗結果
    測試的硬件環境:CPU使用的是AMD Athlon II X2 245處理器,核心數為2,該處理器主頻為2.9 GHz,峰值運算能力約為17.4 GFLOPS;GPU使用的是NVIDIA GeForce 9800M GTS,有8個SM即有64個SP單元,顯存帶寬為51.2 GB/s,GPU核心頻率為0.625 GHz,單精度浮點計算能力為240 GFLOPS,屬于NVIDIA中端顯卡。測試的軟件環境:Windows XP系統,CUDA toolkit 3.0,Visual Studio 2008,CUDA計算能力為1.1。
    在程序運行的測試中,對矩陣規模由256×256~2 048×2 048逐漸增大,實驗數據均是三次測試取得的平均值,這樣實驗的結果更準確。加速比是指程序在CPU上運行的時間與程序在GPU上運行所需的時間之比。峰值比是指運算速度與GPU單精度浮點運算能力之比。最后求得在各種矩陣規模運行下的加速比及峰值比。實驗結果如表1所示。

    實驗結果表明:當矩陣維數小于320×320時,帶狀劃分加速比小于1,說明CPU運算時間要小于一維帶狀劃分時GPU的運算時間,這說明GPU計算時,從內存復制矩陣到顯存和把結果矩陣從顯存拷貝回內存過程中消耗了一些時間[6]。隨著矩陣維數的增大,CPU的運算時間呈現級數增長,而GPU運算時間只是小幅度增長。此時GPU強大的浮點運算能力凸顯出來,加速比在矩陣維數為2 048時最大為1 079.64,CPU上Intel MKL矩陣乘法比文中所用的CPU矩陣乘法快了200多倍,但是依靠GPU流多處理的并行執行能力,GPU上的實現方法還是比Intel MKL快了5倍左右。運用CUDA的軟硬件架構使得GPU合理組織數據,使得內存的讀取節省了大量時間。峰值比也有很大的提高,峰值比說明了算法對GPU強大浮點運算能力的利用,對GPU相應算法的對比具有很高的參考價值。
    通過矩陣乘法在CPU與GPU上不同的性能表現可以發現,NVIDIA公司推出的CUDA使某些大運算量的計算可以從大型計算機或者超級計算機轉移到個人PC,這一新技術不僅使科研縮減了成本,同時也為科學領域進行大規模運算提供了新方法[7]。對于它的未來值得期待,畢竟CUDA已經在影視制作、計算金融、流體力學、醫學成像、石油天然氣數據收集、地質勘探及超級計算機的建立等領域取得了成功。
參考文獻
[1] NVIDIA Corporation.NVIDIA CUDA Programming Guide  Version3.0[EB/OL].(2010-02-10)[2011-08-20].http://cuda.csdn.net/.
[2] 張舒,褚艷利,趙開勇,等.GPU高性能并行運算之CUDA[M].北京:中國水利水電出版社,2009.
[3] Ye Zhenyu.GPU assignment 5KK70[DB/OL].(2009-11-05)[2011-09-01].http://wenku.baidu.com/view/9cd2e372027-68e9951e738e5.html.
[4] NVIDIA Corporation.NVIDIA CUDA CUBLAS library PG-00000-002_V3.0[EB/OL].(2010-02-10)[2011-09-10].http://cuda.csdn.net/.
[5] Hotball.深入淺出談CUDA技術[DB/OL].(2008-11-21) [2011-09-15].http://www.pcinlife.com/article/graphics/2008-06-04/1212575164d532_3.html.
[6] 劉進鋒,郭雷.CPU與GPU上幾種矩陣乘法的比較與分析[J].計算機工程與應用,2011,47(19):9-23.
[7] 肖江,胡柯良,鄧元勇.基于CUDA的矩陣乘法和FFT性能測試[J].計算機工程,2009.35(10):7-10.

此內容為AET網站原創,未經授權禁止轉載。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
欧美在线不卡| 欧美激情中文字幕乱码免费| 91久久久亚洲精品| 午夜精品国产| 亚洲欧美资源在线| 亚洲午夜精品福利| 亚洲视频在线免费观看| 亚洲成色www8888| 悠悠资源网亚洲青| 在线观看欧美日韩| 亚洲国产精品福利| 亚洲黄色在线观看| 亚洲欧洲日夜超级视频| 亚洲日本aⅴ片在线观看香蕉| 亚洲国产精品欧美一二99| 亚洲国产高清自拍| 亚洲国产日韩一区二区| 亚洲精品老司机| 日韩一级二级三级| 一区二区三区www| 亚洲一区二区三区色| 午夜久久tv| 久久精品国产77777蜜臀| 亚洲国产精品999| 日韩视频在线免费| 亚洲一区二区在线观看视频| 亚洲伊人伊色伊影伊综合网| 亚洲中字在线| 欧美中文字幕第一页| 久久久国际精品| 欧美大尺度在线| 欧美日韩免费区域视频在线观看| 欧美新色视频| 国产一区白浆| 亚洲国产精品美女| 一区二区久久久久| 性18欧美另类| 亚洲精品久久久久久久久久久| 夜夜嗨av一区二区三区四季av | 玖玖在线精品| 欧美大片免费观看在线观看网站推荐| 欧美精品系列| 国产欧美日韩伦理| 亚洲国产片色| 亚洲欧美国产高清| 亚洲国产日韩一级| 亚洲视频在线看| 久久成人免费日本黄色| 欧美va天堂在线| 国产精品成人观看视频免费| 国产亚洲欧美日韩一区二区| 亚洲国产成人精品女人久久久 | 中文一区二区在线观看| 久久成人免费电影| 欧美成人a∨高清免费观看| 欧美视频一区二区三区四区| 国产亚洲精品一区二555| 亚洲黄网站在线观看| 亚洲自拍偷拍福利| 亚洲精品字幕| 欧美中文字幕视频在线观看| 欧美激情1区2区3区| 国产女优一区| 亚洲欧洲午夜| 欧美伊人影院| 亚洲性色视频| 免费看黄裸体一级大秀欧美| 国产精品国产馆在线真实露脸| 国产一区二区三区丝袜| 99视频在线观看一区三区| 欧美中文在线字幕| 亚洲愉拍自拍另类高清精品| 男女精品网站| 国产伦精品一区二区三区| 亚洲国产精品激情在线观看| 亚洲欧美日韩电影| 99综合在线| 蜜臀av一级做a爰片久久| 国产精品视频免费观看www| 亚洲国产精品国自产拍av秋霞| 亚洲欧美一区在线| 亚洲视频碰碰| 欧美国产成人精品| 国产一区二区三区在线观看精品| 99www免费人成精品| 亚洲国产一二三| 久久爱另类一区二区小说| 欧美日韩精品欧美日韩精品| 好吊成人免视频| 亚洲欧美日韩一区在线观看| 一区二区三区成人精品| 免费h精品视频在线播放| 国产伦精品一区二区三区四区免费| 亚洲卡通欧美制服中文| 91久久极品少妇xxxxⅹ软件| 久久久精品动漫| 国产伦精品一区二区三区免费| 在线性视频日韩欧美| 亚洲美女视频在线观看| 免费观看成人鲁鲁鲁鲁鲁视频| 国产一区二区按摩在线观看| 亚洲免费视频一区二区| 亚洲欧美国产视频| 欧美午夜精品理论片a级按摩| 亚洲另类在线一区| 日韩午夜免费视频| 欧美国产精品中文字幕| 在线精品视频在线观看高清| 久久国产成人| 久久久久久夜精品精品免费| 国产伪娘ts一区| 西西人体一区二区| 欧美在线free| 国产亚洲精品aa| 欧美一区二区在线视频| 久久久www免费人成黑人精品 | 国产精品a久久久久久| 99国产精品久久久久久久成人热| 日韩亚洲在线观看| 欧美激情国产高清| 亚洲精品国产精品乱码不99按摩 | 亚洲韩国青草视频| 亚洲精品视频二区| 欧美成人精品一区二区三区| 亚洲高清色综合| 日韩一级在线观看| 欧美日韩播放| 99视频一区二区| 亚洲欧美区自拍先锋| 国产精品视频久久一区| 亚洲欧美综合精品久久成人| 欧美在线亚洲在线| 国产日韩专区| 亚洲电影免费观看高清完整版在线观看| 久久精品视频免费| 影院欧美亚洲| 99精品视频免费| 国产精品久久999| 午夜精品成人在线| 久久亚洲一区二区| 亚洲第一黄色| 制服丝袜激情欧洲亚洲| 国产精品久久久久永久免费观看| 亚洲欧美日韩精品综合在线观看| 久久国产精品久久久久久| 韩国一区二区在线观看| 亚洲人成小说网站色在线| 欧美精选午夜久久久乱码6080| 一二三区精品福利视频| 久久成人精品| 在线不卡中文字幕| 夜夜爽夜夜爽精品视频| 欧美亚洲第一区| 欧美中在线观看| 欧美日本韩国在线| 亚洲免费一区二区| 麻豆精品视频在线观看| 日韩视频免费在线| 欧美在线1区| 亚洲激情网站免费观看| 亚洲欧美国产视频| 国内成人精品视频| 99精品欧美一区二区三区| 国产精品一区二区三区观看 | 亚洲日韩中文字幕在线播放| 欧美日韩一区在线观看视频| 午夜精品国产精品大乳美女| 蜜桃av综合| 亚洲性图久久| 欧美福利专区| 亚洲伊人网站| 欧美+亚洲+精品+三区| 在线亚洲欧美视频| 蜜臀av性久久久久蜜臀aⅴ四虎| 一本色道久久综合亚洲精品小说 | 国产真实久久| 一区二区91| 狠狠色狠狠色综合| 亚洲线精品一区二区三区八戒| 国产亚洲成av人片在线观看桃| 日韩视频永久免费| 国产亚洲欧美日韩美女| 夜夜嗨av一区二区三区中文字幕 | 久久视频免费观看| 9色国产精品| 美乳少妇欧美精品| 亚洲综合国产精品| 欧美日韩ab| 久久国产精品色婷婷| 国产精品国产三级国产aⅴ9色| 亚洲狠狠丁香婷婷综合久久久| 国产精品久久一区二区三区| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲电影激情视频网站| 亚洲性视频网址| 亚洲国产精品123| 久久九九国产| 亚洲午夜久久久久久久久电影院 | 亚洲国产精品激情在线观看| 欧美一区国产一区|