色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

gemv優化總結

perfxlab ? 來源:澎峰科技PerfXLab ? 2023-05-25 09:08 ? 次閱讀

有朋友來信說:

1. “除了以NVIDIA(英偉達)為例,能不能談點國產GPU優化的經驗分享?”

2. “老講國外的東西,你們能不能支持一下國產CPU和加速卡?“

這里解釋一下原因:

1. N卡的資料和環境大家都比較好找,對于學習GPU并行優化編程的朋友比較友善。

2. 暫時受限于商業保密,我們相信后續會逐步開放起來,學習的平臺和環境也容易找到。到時就可以分享一些國產CPU和加速卡的優化經驗出來。

------ 正文分割線 ------

本文主要是介紹如何對gemv算法進行優化。gemv,即矩陣向量乘,即計算一個矩陣A與一個向量x的乘積,這是并行計算中的經典話題。個人感覺,gemv的優化核心是需要考慮不同shape的情況,然后針對型地進行優化。本篇文章會先介紹一下針對不同shape設計不同的并行算法,然后說明一下優化思路和相關優化技巧,最后說一下實驗效果,在A矩陣列數為16 128的時候,我寫的gemv能擁有超越cublas的性能表現。

一、前言

首先介紹一下gemv算法。給定矩陣A和向量x,gemv需要計算兩者的乘積,示意圖如下:

6a2366c2-fa8c-11ed-90ce-dac502259ad0.png

gemv

二、針對不同shape的并行算法設計

這次講到并行算法設計,什么叫并行算法設計。每個人的理解都不太一樣,在GPU中,我的理解就是:設計block和thread的workload,說白了就是要搞清楚一個block負責哪部分的計算,一個thread要負責哪部分的計算。而設計的原則就是盡可能地減少訪存,提高數據的復用概率,然后讓所有的處理器都滿負荷地進行工作,不能浪費。

2.1 針對n=32

對于n=32的情況,我們將每個block設置為256個線程,4個warp,然后每個warp負責一行元素的計算。每個warp要對x進行訪問,然后在warp內部進行一次reduce求和操作。

6a38baf4-fa8c-11ed-90ce-dac502259ad0.jpg

n=32

代碼如下:

template 
__device__ __forceinline__ float warpReduceSum(float sum) {
    if (WarpSize >= 32)sum += __shfl_down_sync(0xffffffff, sum, 16); // 0-16, 1-17, 2-18, etc.
    if (WarpSize >= 16)sum += __shfl_down_sync(0xffffffff, sum, 8);// 0-8, 1-9, 2-10, etc.
    if (WarpSize >= 8)sum += __shfl_down_sync(0xffffffff, sum, 4);// 0-4, 1-5, 2-6, etc.
    if (WarpSize >= 4)sum += __shfl_down_sync(0xffffffff, sum, 2);// 0-2, 1-3, 4-6, 5-7, etc.
    if (WarpSize >= 2)sum += __shfl_down_sync(0xffffffff, sum, 1);// 0-1, 2-3, 4-5, etc.
    return sum;
}

// if N == 32
__global__ void Sgemv_v0( 
    float * __restrict__ A,
    float * __restrict__ x,
    float * __restrict__ y, 
    const int M,
    const int N) {
    // Block index
    int bx = blockIdx.x;

    // Thread index
    int tx = threadIdx.x;
    int ty = threadIdx.y;

    const int warp_size=32;
    int laneId= tx % warp_size;
    int current_row = blockDim.y * bx + ty;

    if(current_row < M){
        float res=0;
        int kIteration = N/warp_size;
        if(kIteration==0) kIteration=1;
        #pragma unroll
        for(int i=0; i< kIteration; i++){
            int current_col = i*warp_size + laneId;
            res += A[current_row*N + current_col] * x[current_col];
        }
        res = warpReduceSum(res);
        if(laneId==0) y[current_row]=res;
    }
}

2.2 針對n=128

對于n=128的情況,同樣讓warp負責一行元素的計算,但是因為每行的元素比較多,所以采用了float4進行向量化的訪存。能夠有更高的訪存效率。

6a53326c-fa8c-11ed-90ce-dac502259ad0.jpg

n=128

代碼如下:

template 
__device__ __forceinline__ float warpReduceSum(float sum) {
    if (WarpSize >= 32)sum += __shfl_down_sync(0xffffffff, sum, 16); // 0-16, 1-17, 2-18, etc.
    if (WarpSize >= 16)sum += __shfl_down_sync(0xffffffff, sum, 8);// 0-8, 1-9, 2-10, etc.
    if (WarpSize >= 8)sum += __shfl_down_sync(0xffffffff, sum, 4);// 0-4, 1-5, 2-6, etc.
    if (WarpSize >= 4)sum += __shfl_down_sync(0xffffffff, sum, 2);// 0-2, 1-3, 4-6, 5-7, etc.
    if (WarpSize >= 2)sum += __shfl_down_sync(0xffffffff, sum, 1);// 0-1, 2-3, 4-5, etc.
    return sum;
}

// if N>= 128
__global__ void Sgemv_v1( 
    float * __restrict__ A,
    float * __restrict__ x,
    float * __restrict__ y, 
    const int M,
    const int N) {
    // Block index
    int bx = blockIdx.x;

    // Thread index
    int tx = threadIdx.x;
    int ty = threadIdx.y;

    const int warp_size=32;
    int laneId= tx % warp_size;
    int current_row = blockDim.y * bx + ty;

    if(current_row < M){
        float res=0;
        int kIteration = (N/warp_size)/4;
        if(kIteration==0) kIteration=1;
        A = &A[current_row*N];
        #pragma unroll
        for(int i=0; i< kIteration; i++){
            int current_col_vec = (i*warp_size + laneId);
            float4 current_val= reinterpret_cast(A)[current_col_vec];
            float4 current_x = reinterpret_cast(x)[current_col_vec];
            res += current_val.x*current_x.x;
            res += current_val.y*current_x.y;
            res += current_val.z*current_x.z;
            res += current_val.w*current_x.w;
        }
        res = warpReduceSum(res);
        if(laneId==0) y[current_row]=res;
    }
}

2.3 針對n=16

對于n=16的情況,讓一個warp負責兩行元素的計算。以warp0為例,0-15號線程負責第0行元素的計算,而16-31號線程負責第1行元素的計算。

6a6a3796-fa8c-11ed-90ce-dac502259ad0.jpg

n=16

代碼如下:

template 
__device__ __forceinline__ float warpReduceSum(float sum) {
    if (WarpSize >= 32)sum += __shfl_down_sync(0xffffffff, sum, 16); // 0-16, 1-17, 2-18, etc.
    if (WarpSize >= 16)sum += __shfl_down_sync(0xffffffff, sum, 8);// 0-8, 1-9, 2-10, etc.
    if (WarpSize >= 8)sum += __shfl_down_sync(0xffffffff, sum, 4);// 0-4, 1-5, 2-6, etc.
    if (WarpSize >= 4)sum += __shfl_down_sync(0xffffffff, sum, 2);// 0-2, 1-3, 4-6, 5-7, etc.
    if (WarpSize >= 2)sum += __shfl_down_sync(0xffffffff, sum, 1);// 0-1, 2-3, 4-5, etc.
    return sum;
}

// if N <= 16
template <
    const int ROW_PER_WARP
    > 
__global__ void Sgemv_v2( 
    float * __restrict__ A,
    float * __restrict__ x,
    float * __restrict__ y, 
    const int M,
    const int N) {
    // Block index
    int bx = blockIdx.x;

    // Thread index
    int tx = threadIdx.x;
    int ty = threadIdx.y;

    const int warp_size=32;
    int laneId= tx % warp_size;
    int current_warp_row = (blockDim.y * bx + ty) * ROW_PER_WARP;
    const int kWarp_size = warp_size / ROW_PER_WARP;
    int kLaneId = laneId % kWarp_size;
    int current_thread_row = current_warp_row + laneId / kWarp_size;

    if(current_thread_row < M){
        float res=0;
        int current_col = kLaneId;
        res += A[current_thread_row * N + current_col] * x[current_col];
        res = warpReduceSum(res);
        if(kLaneId==0) y[current_thread_row]=res;
    }
}

三、優化思路:

上一節說明了如何針對不同維度的n進行優化,這一節說明一下為什么要這么設計,以及這樣的設計方式能夠帶來什么樣的好處。主要考慮的因素有兩個,如下:

3.1 盡可能地讓warp中的32個線程忙碌

這個主要是針對n<32的情況,例如n=16,如果使用一個warp來負責一行元素的計算,那么warp中有一半的元素都是浪費的。所以讓一個warp來負責多行元素的計算,這樣讓32個線程全部忙碌起來。

3.2 盡可能地提高訪存效率

① global mem->register

將數據從global memory搬運到寄存器上時,最重要的就是考慮是不是進行了合并訪存。在這里,我們只考慮矩陣數據在global mem中是地址對齊的,即n是2的多次冪。上述的三種并行實現中,warp中的32個線程都是連續地訪問32個float或者128個float,因而滿足了合并訪存的條件,確保了global -> register的訪存效率。

② shared mem->register

說到這里,可能會有讀者好奇,上述的代碼都沒有用到shared mem。為啥要說這個點。我們可以再仔細看看上述的三種并行實現,以第2種為例,一個block中有4個warp,每個warp都需要對x進行一次global上的訪存,所以一個block有4次訪存。如果將x存儲到shared mem中,4個warp都去訪問shared mem上的x,這樣的話,對于global的訪存就從4次變成1次。直觀上會有性能提升,但不幸的是,如果用shared mem的話,將global mem的數據搬運至shared mem需要有同步操作,這又會導致性能的下降。總的來說,使用shared mem并沒有得到顯著的提升,不過還是在這里說明一下。

③ 向量化訪存

向量化訪存就是一個老生常談的話題了,說白了就是盡可能地使用128bit的訪存指令,這個在reduce、sgemm、elementwise專題上說了很多,就不再多說。

四、實驗與總結

筆者在V100上進行了實驗,迭代1000次,用nsight進行了測試,性能數據如下:

sgemv M N my_sgemv time(ns) cublas(ns) my_sgemv/cublas
v0 16384 32 10341 8386 81.1%
v1 16384 128 14284 15848 110.9%
v2 16384 16 6903 7576 109.7%

可以看出,在n=16以及n=128的情況下,都比cublas性能要好。n=32的情況要差于cublas。如果再加上向量化訪存應該能夠有更好的性能表現。由于我實在沒時間再進行深入,有心的同學可以改改代碼看看效果 :)。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10878

    瀏覽量

    212167
  • 存儲
    +關注

    關注

    13

    文章

    4328

    瀏覽量

    85942
  • 編程
    +關注

    關注

    88

    文章

    3627

    瀏覽量

    93809
  • 澎峰科技
    +關注

    關注

    0

    文章

    55

    瀏覽量

    3178

原文標題:深入淺出GPU優化系列:gemv優化

文章出處:【微信號:perfxlab,微信公眾號:perfxlab】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    HBase性能優化方法總結

    hbase響應速度;9. 避免出現region熱點現象,啟動按照table級別進行balance。以上是對HBase性能優化方法的概要總結,有HBase性能優化需求的,可以在此基礎上延伸學習,會有一定收獲的!
    發表于 04-20 17:16

    改善深層神經網絡--超參數優化、batch正則化和程序框架 學習總結

    《深度學習工程師-吳恩達》02改善深層神經網絡--超參數優化、batch正則化和程序框架 學習總結
    發表于 06-16 14:52

    文檔基于DSP的視頻監控系統的優化仿真的設計總結文檔

    該文檔為基于DSP的視頻監控系統的優化仿真的設計總結文檔,是一份很不錯的參考資料,具有較高參考價值,感興趣的可以下載看看………………針對目前IGBT驅動電路復雜的缺點,本文以德國西門康公司
    發表于 08-27 16:19

    嵌入式Java虛擬機優化技術總結的太棒了

    嵌入式Java虛擬機優化技術總結的太棒了
    發表于 04-25 06:47

    總結下電機控制中對程序算法優化的辦法

    (用到了三角函數)都比較消耗電機主控芯片的計算能力。在考慮算法實現的時候,都需要針對主控芯片的實際性能進行一定優化,才能確保算法能夠順利運行。這里我總結下電機控制中對程序算法優化的辦法。數據的概念浮點數
    發表于 08-27 06:37

    電機控制中對程序算法優化的辦法總結

    (用到了三角函數)都比較消耗電機主控芯片的計算能力。在考慮算法實現的時候,都需要針對主控芯片的實際性能進行一定優化,才能確保算法能夠順利運行。這里我總結下電機控制中對程序算法優化的辦法。數據的概念...
    發表于 09-07 06:19

    GPRS優化思路總結報告

    GPRS優化思路總結報告:一、概述 2二、無線優化的思路 2三、(E)GPRS網絡資源容量分析優化 53.1、(E)GPRS網絡拓撲結構 63.
    發表于 07-27 21:29 ?26次下載

    DSP程序優化總結

    DSP程序優化總結
    發表于 10-23 14:24 ?2次下載
    DSP程序<b class='flag-5'>優化</b><b class='flag-5'>總結</b>

    區塊鏈共識算法的效能優化研究及總結

    。由于共識算法的資源花銷、能源耗費以及性能之間相互關聯且關系復雜,因此有必要從¨效能”的角度對現有區塊鏈的共識算法加以分析,并總結研究思路。文中總結了區塊鏈共識算法的效能優化研究進展。首先定義區塊鏈共識算法的效
    發表于 04-25 11:35 ?4次下載
    區塊鏈共識算法的效能<b class='flag-5'>優化</b>研究及<b class='flag-5'>總結</b>

    TD-LTE網絡優化經驗總結解析

    TD-LTE網絡優化經驗總結解析說明。
    發表于 04-27 10:30 ?23次下載

    DC-DC電源系統的優化設計總結

    DC-DC電源系統的優化設計總結(電源技術期刊咋樣)-該文檔為DC-DC電源系統的優化設計總結文檔,是一份不錯的參考資料,感興趣的可以下載看看,,,,,,,,,,,,,,,,,
    發表于 09-22 11:45 ?26次下載
    DC-DC電源系統的<b class='flag-5'>優化</b>設計<b class='flag-5'>總結</b>

    接口優化的常見方案實戰總結

    針對老項目,去年做了許多降本增效的事情,其中發現最多的就是接口耗時過長的問題,就集中搞了一次接口性能優化。本文將給小伙伴們分享一下接口優化的通用方案。
    的頭像 發表于 03-06 09:22 ?581次閱讀

    深入淺出GPU優化系列:gemv優化

    這次講到并行算法設計,什么叫并行算法設計。每個人的理解都不太一樣,在GPU中,我的理解就是:設計block和thread的workload,說白了就是要搞清楚一個block負責哪部分的計算,一個thread要負責哪部分的計算。
    的頭像 發表于 05-25 09:03 ?2311次閱讀
    深入淺出GPU<b class='flag-5'>優化</b>系列:<b class='flag-5'>gemv</b><b class='flag-5'>優化</b>

    總結FasterTransformer Encoder優化技巧

    FasterTransformer BERT 包含優化的 BERT 模型、高效的 FasterTransformer 和 INT8 量化推理。
    的頭像 發表于 05-30 15:15 ?1314次閱讀
    <b class='flag-5'>總結</b>FasterTransformer Encoder<b class='flag-5'>優化</b>技巧

    性能優化之路總結

    針對老項目,去年做了許多降本增效的事情,其中發現最多的就是接口耗時過長的問題,就集中搞了一次接口性能優化。本文將給小伙伴們分享一下接口優化的通用方案。 ? ? 一、接口優化方案總結 1
    的頭像 發表于 06-17 15:00 ?353次閱讀
    主站蜘蛛池模板: 亚洲免费久久| 日韩免费精品视频| 欧美日韩一二区旡码高清在线| 掀开奶罩边躁狠狠躁软学生| YELLOW高清视频免费观看| 麻豆影视在线直播观看免费| 一本色道久久综合一区 | 出轨的妻子在线观看| 萝莉御姐被吸奶| 最新亚洲人成网站在线影院| 狠狠人妻久久久久久综合九色| 亚洲国产成人精品无码区5566 | 99久久99久久精品| 蜜柚在线观看免费高清官网视频 | 夜色女人香| 久久精品国产免费播放| 野花视频在线观看免费| 久久re这里视频只有精品首页 | 亚洲第一伊人| 饥渴的40岁熟妇完整版在线| 亚洲色t图| 久久永久视频| 999av视频| 日韩hd高清xxxⅹ| 国产成在线观看免费视频| 十九岁在线观看免费完整版电影 | 色综合久久网女同蕾丝边| 风流少妇BBWBBW69视频| 无码AV精品一区二区三区| 国产亚洲国际精品福利| 樱花之恋动漫免费观看| 内射人妻骚骚骚| 白丝萝莉喷水| 乡村教师电影版| 久久人妻少妇嫩草AV无码| 99手机在线视频| 四虎国产精品高清在线观看| 好看的电影网站亚洲一区| 777米奇影院第七色色| 三级网址在线观看| 激情女人花|