0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CUDA矩陣乘法優(yōu)化手段詳解

我快閉嘴 ? 來(lái)源:曠視研究院 ? 作者:馬駿 ? 2022-09-28 09:46 ? 次閱讀

單精度矩陣乘法(SGEMM)幾乎是每一位學(xué)習(xí) CUDA 的同學(xué)繞不開(kāi)的案例,這個(gè)經(jīng)典的計(jì)算密集型案例可以很好地展示 GPU 編程中常用的優(yōu)化技巧。本文將詳細(xì)介紹 CUDA SGEMM 的優(yōu)化手段,適合認(rèn)真閱讀過(guò)《CUDA C++Programming Guide》,具備一定 CUDA 編程基礎(chǔ)的同學(xué)閱讀,希望能給追求極致性能的同學(xué)們一些啟發(fā)。

CUDA 矩陣乘法優(yōu)化手段詳解

Naive 實(shí)現(xiàn)的分析:到底差在哪里?

筆者面試過(guò)不少具有 CUDA 編程經(jīng)驗(yàn)的校招同學(xué),當(dāng)提問(wèn)使用 CUDA 編寫(xiě)一個(gè) SGEMM Kernel 的時(shí)候,通常會(huì)獲得這么一個(gè)答案:

__global__voidmatrixMul(constfloat*A,constfloat*B,float*C,
intM,intN,intK){
inttx=blockIdx.x*blockDim.x+threadIdx.x;
intty=blockIdx.y*blockDim.y+threadIdx.y;
if(ty

這樣一個(gè) Naive 的 Kernel 當(dāng)然不是筆者所期待的,因?yàn)檫@個(gè) Kernel 的性能基本可以斷定連 cublas 的 1/10 都不到,顯然不符合我們追求高性能的需求。那么這個(gè) Naive 的實(shí)現(xiàn)究竟差在哪呢?

分析代碼我們可以看到,計(jì)算一次 FMA(乘累加)之前需要讀一次 A 和讀一次 B,眾所周知,讀取 Global Memory 的代價(jià)很大,通常都需要幾百個(gè) cycle(時(shí)鐘周期),而計(jì)算一次 FMA 通常只需要幾個(gè) cycle,大量的時(shí)間被花費(fèi)在了訪存上。也許有思維活絡(luò)的同學(xué)立馬想到,可以將 A 和 B 矩陣先搬運(yùn)到 Shared Memory(SM 中低延遲的 on-chip memory,block 內(nèi)線程共享,附 NVIDIA GPU 內(nèi)存結(jié)構(gòu)圖)中降低訪存的開(kāi)銷,這的確是一個(gè)很好的思路,但是這只能將訪存代價(jià)從幾百 cycle 降低到幾十 cycle,并不改變問(wèn)題的本質(zhì)。問(wèn)題的關(guān)鍵在于主體循環(huán)由兩條 Load 指令與一條 FMA 指令構(gòu)成,計(jì)算指令只占總體的 1/3,計(jì)算訪存比過(guò)低,最終導(dǎo)致了訪存延遲不能被隱藏,從而性能不理想。

f715e67a-3e19-11ed-9e49-dac502259ad0.jpg

讓我們打開(kāi)思路,若一個(gè) thread 并不只計(jì)算一個(gè)結(jié)果,而是計(jì)算 4x4 個(gè)結(jié)果,并且使用 Shared Memory 優(yōu)化,Hot Loop 會(huì)是什么樣呢,偽代碼如下所示:

floatc[4][4]={{0}};
floata_reg[4];
floatb_reg[4];
for(inti=0;i

分析可以得出從 smemA 讀取到寄存器 a_reg 中,需要進(jìn)行 4 次訪存操作,B 同理,那么主體的計(jì)算訪存指令比例變成了 16/8,相對(duì)于之前的情況,計(jì)算指令的占比大大提高了。足夠大的計(jì)算訪存比能提升計(jì)算單元的利用率,并能起到隱藏訪存延遲的作用。我們可以進(jìn)一步提升計(jì)算訪存比,從而使得 kernel 的性能接近理論峰值。

矩陣分塊與資源分配

顯然我們不能只使用一個(gè) block 計(jì)算一個(gè)超大矩陣,這樣會(huì)造成大量 SM(Streaming Multiprocessor)的閑置浪費(fèi),這就需要對(duì)矩陣進(jìn)行分塊計(jì)算,如下圖所示:

f72b26a2-3e19-11ed-9e49-dac502259ad0.jpg

不同的分塊大小在不同 shape 的矩陣乘法應(yīng)用上性能各有優(yōu)劣,本文選取 128x128 的分塊舉例。

從上一小節(jié)我們可以看到,提升計(jì)算訪存比有很大的好處,那么計(jì)算訪存比可以無(wú)限提升嗎,答案是否定的。因?yàn)橐嵘?jì)算訪存比,單個(gè) thread 就需要計(jì)算一個(gè)更大的塊,這就需要更多的寄存器,但寄存器的個(gè)數(shù)是有限的。以 Turing 架構(gòu)的 GPU 為例,單個(gè) SM 的寄存器總量為 65536,因?yàn)橹噶罹幋a的限制,單個(gè) thread 能使用的最大寄存器個(gè)數(shù)為 255,并且寄存器個(gè)數(shù)并不是用得越多越好。這里需要引入一個(gè) Occupancy(占用率)的概念,Occupancy 是指每個(gè) SM 中活動(dòng)線程束(Warp)數(shù)量與最大并發(fā)線程束數(shù)量的比值,高的 Occupancy 不一定意味著高性能,但可以通過(guò)切換執(zhí)行 Warp 來(lái)起到一定隱藏延遲的作用。而每個(gè) SM 中的 Active Warp 數(shù)量,取決于 block 使用的資源數(shù)量,具體為每個(gè)線程使用的寄存器個(gè)數(shù)與 Shared Memory 用量。Occupany可通過(guò) CUDA Toolkit 中提供的 CUDA_Occupancy_Calculator.xls 工具獲得。

考慮一個(gè) block 計(jì)算 128x128 的分塊,若每個(gè)線程計(jì)算 128 個(gè)結(jié)果,需要的 block size 為 128,單個(gè)線程需要 128 個(gè)寄存器儲(chǔ)存計(jì)算結(jié)果,加上所需的 Gmem to Smem,Smem to Reg 等一些所需的寄存器,大概共需要至少 180 多個(gè),計(jì)算 Occupany 可知此時(shí)的 Active Warp 數(shù)只有 8,Occupany 為 25%;若設(shè)置 block size 為 256,則每個(gè)線程僅需計(jì)算 64 個(gè)結(jié)果,調(diào)整寄存器和 Shared Memory 的使用量并觀察 Occupany,可知若每個(gè)線程只使用 128 個(gè)寄存器,block 內(nèi)的 Shared Memory 使用量限制在 32K,Active Warp 數(shù)可以達(dá)到 16,是一個(gè)更優(yōu)的選擇:

f7438472-3e19-11ed-9e49-dac502259ad0.jpg

并且此時(shí)的配置計(jì)算訪存比可以達(dá)到 64/4(使用向量讀取),已經(jīng)足夠隱藏訪存延遲。

極致的訪存優(yōu)化

通常情況下,在選取了合適的 block 資源配置,利用 Shared Memory 降低訪存延遲,做好循環(huán)展開(kāi)之后,SGEMM Kernel 的性能已經(jīng)能達(dá)到一個(gè)不錯(cuò)的水平(80% cublas),但這并不是我們旅程的終點(diǎn)。首先,我們可以使用向量讀取指令LDS.128優(yōu)化 Shared Memory 訪問(wèn)(對(duì)應(yīng) float4 數(shù)據(jù)類型),這能大幅減少訪存指令的數(shù)量,進(jìn)一步提升計(jì)算訪存比,由此我們需要將 A 矩陣存入 smemA 之前做一次轉(zhuǎn)置:

f7566baa-3e19-11ed-9e49-dac502259ad0.jpg

同時(shí),我們的 kernel 為 256 個(gè)線程計(jì)算 128x128 的分塊,為了能夠合并訪問(wèn) Shared Memory,我們將 256 個(gè)線程劃為二維,令:

inttx=threadIdx.x%16;
intty=threadIdx.x/16;

并按照如下方式向量讀取 Shared Memory 中的數(shù)據(jù):

f7736796-3e19-11ed-9e49-dac502259ad0.jpg

最終單個(gè)線程計(jì)算 2x2 個(gè) 4x4 的結(jié)果,結(jié)果布局如圖所示:

f7996e96-3e19-11ed-9e49-dac502259ad0.jpg

并且通過(guò) micro benchmark 可以探測(cè)出,Turing(Tesla T4) 的 Global Memory 的訪存延遲約 300 cycle,Shared Memory 的訪存延遲在約 30 cycle,需要充分利用 Prefetch 的思想,隱藏 Global Memory 讀入中間寄存器、將來(lái)自 Global Memory 的數(shù)據(jù)塊寫(xiě)入 Shared Memory、從 Shared Memory 中讀出數(shù)據(jù)塊的訪存延遲,以免計(jì)算單元因?yàn)?stall 而空閑太久,最終的偽代碼如下所示:

#defineTILE_K16
__shared__float4smemA[2][TILE_K*128/4];
__shared__float4smemB[2][TILE_K*128/4];
float4c[8][2]={{make_float4(0.f,0.f,0.f,0.f)}};
float4ldg_a_reg[2];
float4ldg_b_reg[2];
float4a_reg[2][2];
float4b_reg[2][2];

//transferfirsttilefromglobalmemtosharedmem
load_gmem_tile_to_reg(A,0,ldg_a_reg);
load_gmem_tile_to_reg(B,0,ldg_b_reg);

store_reg_to_smem_tile_transpose(ldg_a_reg,0,smemA[0]);
store_reg_to_smem_tile(ldg_b_reg,0,smemB[0]);
__syncthreads();

//loadfirsttilefromsharedmemtoregister
load_smem_tile_to_reg(smemA[0],0,a_reg[0]);
load_smem_tile_to_reg(smemB[0],0,b_reg[0]);

intwrite_stage_idx=1;//pingpongswitch
do{
i+=TILE_K;
//loadnexttilefromglobalmem
load_gmem_tile_to_reg(A,i,ldg_a_reg);
load_gmem_tile_to_reg(B,i,ldg_b_reg);

intload_stage_idx=write_stage_idx^1;

#pragmaunroll
for(intj=0;j

注:此處偷懶假設(shè)了 M、N、K 都是 4 的倍數(shù),若非 4 的倍數(shù)則 Global Memory 不能使用 float4 進(jìn)行讀取,結(jié)果也不能用 float4 進(jìn)行寫(xiě)回,而且為了合并寫(xiě)回,需要通過(guò) Shared Memory 交換 warp 內(nèi)的結(jié)果,保證每個(gè) warp 執(zhí)行一條 Store 指令能夠?qū)懟匾黄B續(xù)的內(nèi)存空間。

至此我們獲得了一個(gè)充分優(yōu)化的 SGEMM Kernel。另外 Ampere GPU 新增了LDGSTS指令,數(shù)據(jù)塊從 Global Memory 到 Shared Memory 的過(guò)程不需要經(jīng)過(guò)中間寄存器,可以進(jìn)一步的優(yōu)化 SGEMM 的性能。

性能對(duì)比

為了避免 cublas 選取到 split K 的 Kernel,我們將 K 固定為 1024,取 M, N = 2048, 4096, 8192 和 16384 作為測(cè)試用例,對(duì)比了上述 SGEMM Kernel 與 cublas 的性能(測(cè)試 GPU 為 Tesla T4,鎖定核心頻率為 1100):

f7ae752a-3e19-11ed-9e49-dac502259ad0.jpg

可以看到所實(shí)現(xiàn)的 SGEMM Kernel 達(dá)到了 cublas 平均 97.5% 的性能。

超越 cublas:使用 SASS 調(diào)優(yōu) Kernel

到這里,可能有同學(xué)依然有一個(gè)疑問(wèn),我們似乎把所有能想到的優(yōu)化手段都用上了,為什么寫(xiě)出來(lái)的 CUDA C Kernel 依然離 cublas 有一定的差距,答案是 cublas 所使用的 kernel 中有一大部分并不是通過(guò) nvcc 編譯的 CUDA Kernel,而是使用 NVIDIA GPU 的匯編語(yǔ)言(Shader Assembly,簡(jiǎn)稱 SASS)編寫(xiě)的深度調(diào)優(yōu)版本。

盡管 nvcc 編譯器在不斷的進(jìn)步,特別是 CUDA 11 中的 nvcc,所編譯的 Kernel 與手工匯編優(yōu)化版本之間的差距已大幅縮小,但仍然無(wú)法完全避免寄存器 Bank conflict 的影響以及充分利用寄存器的 Reuse Cache(這兩個(gè)概念下面會(huì)進(jìn)行詳細(xì)的介紹),使得差距仍然存在。即使 PTX 這樣的偽匯編語(yǔ)言,也無(wú)法精確控制寄存器的分配,和 CUDA C 面臨著一樣的困境。

所以為了充分挖掘 GPU 的性能極限,需要對(duì) GPU 指令和寄存器進(jìn)行精確控制,就必須交由 GPU 原生匯編語(yǔ)言 SASS 完成。這方面已經(jīng)有了很多研究,如出自 Citadel 的深入研究 NV GPU 架構(gòu)的 Dissecting the NVidia XXX GPU architecture via microbenchmarking 系列論文,這一系列文章對(duì)底層架構(gòu)做了系統(tǒng)的測(cè)試、分析和總結(jié),雖然其中某些結(jié)論可能并不準(zhǔn)確,但總體來(lái)講有很高的參考價(jià)值。同時(shí)催生了不少開(kāi)源匯編器如 KeplerAs、maxas(最成熟,影響深遠(yuǎn))、turingas 和 CuAssembler 等一系列開(kāi)源 SASS 匯編器,使得使用 SASS 編寫(xiě)高性能 Kernel 變成了可能。

寄存器 Bank conflict

我們知道 Shared Memory 有 Bank conflict,而寄存器的 Bank conflict 也是類似的概念。NVIDIA GPU 每個(gè) SM 有獨(dú)立的 Register File,而 Register File 被分為若干個(gè) Bank,以 Maxwell 為例,若一條指令所需的源寄存器有 2 個(gè)以上來(lái)自于同一 Bank,則會(huì)產(chǎn)生 conflict,指令會(huì)相當(dāng)于重發(fā)射,浪費(fèi)一個(gè) cycle。Maxwell/Pascal 的 Register File 的 Bank 數(shù)為 4,寄存器的id%4即為該寄存器的所屬 bank(如 R0 屬于 Bank 0,R5 屬于 Bank 1),FFMA R1, R0, R4, R1這樣的指令就會(huì)產(chǎn)生寄存器 Bank conflict。而 Turing 架構(gòu)做了改進(jìn),Register File 被分為 2 個(gè) Bank,每個(gè) Bank 有 2 個(gè) Port,若非三個(gè)源寄存器 id 同奇偶則不會(huì)產(chǎn)生沖突,大大緩解了寄存器 Bank conflict。

maxas 中的 Maxwell SGEMM SASS Kernel 為了緩解寄存器 Bank conflict,就對(duì)參與 FFMA 計(jì)算的寄存器做了精巧的分配(參考 maxas 的 SGEMM 文檔),如下圖所示:

f7ea028e-3e19-11ed-9e49-dac502259ad0.jpg

經(jīng)過(guò)對(duì) C 的巧妙排布,寄存器 Bank conflict 大大減少,但依然無(wú)法完全避免(如上圖中黑框標(biāo)識(shí)的部分,A/B 所使用的寄存器會(huì)產(chǎn)生 Bank conflict),這部分沖突就需要用到寄存器 Reuse 來(lái)消除。

Register Reuse

寄存器 Reuse 是 NVIDIA 為了緩解寄存器 Bank conflict 的問(wèn)題,在 Maxwell 開(kāi)始引入的一種機(jī)制,NVIDIA 在讀取指令操作數(shù)的 Collector 單元加入了寄存器的 Reuse Cache。Reuse Cache 是只讀的,指令獲取 Operand 是否通過(guò)此 Cache 由該指令的 control code(maxas 的 control code wiki中有詳細(xì)的介紹)所指定,使用 cuobjdump 反匯編一些 Kernel 可以發(fā)現(xiàn)一些寄存器后有 .reuse的 flag,即表示該寄存器從 Reuse Cache 而非 Register File 中取值,從而消除寄存器 Bank conflict:

#MaxwellGPU
FFMAR2,R64.reuse,R73,R2;#R64進(jìn)入ReuseCache
FFMAR3,R64.reuse,R72,R3;#R64從ReuseCache中獲取,避免與R72沖突

但是使用 .reuse需要滿足一定條件(寄存器將被改寫(xiě)前不能設(shè)置 .reuse),胡亂設(shè)置 reuse flag 會(huì)有可能獲取的是歷史值,造成計(jì)算錯(cuò)誤,根據(jù)筆者的理解,.reuse更像是使該寄存器的值在 Reuse Cache 中 hold 住的標(biāo)識(shí)。nvcc 編譯 CUDA Kernel 也會(huì)使用 Reuse Cache 去規(guī)避一些寄存器 Bank conflict,但是因?yàn)榧拇嫫鞣峙浼爸噶钆挪嫉脑?,Reuse 的利用率并不高,反匯編我們剛才寫(xiě)的 SGEMM Kernel,對(duì)主循環(huán)的所有 FFMA 指令做個(gè)統(tǒng)計(jì),可以發(fā)現(xiàn) Reuse Cache 僅達(dá)到 20% 左右,而 maxas 的 SASS Kernel 通過(guò)設(shè)計(jì)使得 Reuse 的利用率可以達(dá)到 49%。

最終通過(guò) SASS 精細(xì)調(diào)優(yōu)的 SGEMM Kernel 的性能可以全面超越 cublas,感興趣的同學(xué)們可以自行編譯 maxas 中的 SGEMM Kernel 在 Maxwell 或者 Pascal GPU 上進(jìn)行測(cè)試。最后,雖然使用 SASS 能充分挖掘 GPU 的性能,但面臨有三大問(wèn)題:1. 第三方 NV GPU 匯編器依賴于對(duì) GPU 架構(gòu)的逆向研究,可能因?yàn)闆](méi)有探究到全部的硬件底層細(xì)節(jié)而存在未知的 BUG;2. 匯編 Kernel 難于開(kāi)發(fā),更難于調(diào)試;3. NV 每一代 GPU 的 ISA(指令集)都不盡相同,需要不斷開(kāi)發(fā)對(duì)應(yīng)的匯編器和匯編 Kernel。正因?yàn)檫@幾大問(wèn)題的存在,使得使用 SASS 編寫(xiě) Kernel 是個(gè)費(fèi)時(shí)費(fèi)力的工作,除非有追求極致性能的需求,否則不建議輕易嘗試。

GEMM 的延伸:優(yōu)化卷積運(yùn)算

我們都知道優(yōu)化卷積運(yùn)算可以通過(guò) im2col 將卷積映射為矩陣乘法來(lái)實(shí)現(xiàn),對(duì)于上述 SGEMM Kernel,只需要將 Global Memory 的數(shù)據(jù)搬運(yùn)到 Shared Memory 這一過(guò)程稍作修改,由對(duì)應(yīng)位置的映射變?yōu)?im2col 映射,SGEMM Kernel 就搖身一變成為了計(jì)算 Conv 的 Kernel,這即是 cudnn 卷積運(yùn)算的 Implicit Gemm 算法。而在 im2col 過(guò)程中,若直接計(jì)算指針的偏移量的話,會(huì)引入大量的整數(shù)除法和取余運(yùn)算,這是一筆不小的開(kāi)銷,所以可以將地址的偏移量在 host 端預(yù)先計(jì)算好,作為 param 傳入 kernel 中,則可以在需要時(shí)從常量?jī)?nèi)存中讀取,避免整數(shù)除法和取余,實(shí)現(xiàn) Implicit Precomp Gemm。

總結(jié)

本文詳細(xì)介紹了如何編寫(xiě)一個(gè)高效率的 CUDA SGEMM Kernel,并且介紹了使用 SASS 編程這一極限優(yōu)化性能的手段,并稍稍延伸展開(kāi)了通過(guò) Implicit Gemm 優(yōu)化卷積運(yùn)算的思路,希望可以給予有志于極致挖掘硬件性能的同學(xué)們一定的啟發(fā)。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3543

    瀏覽量

    93469
  • CUDA
    +關(guān)注

    關(guān)注

    0

    文章

    121

    瀏覽量

    13570

原文標(biāo)題:CUDA 矩陣乘法終極優(yōu)化

文章出處:【微信號(hào):3D視覺(jué)工坊,微信公眾號(hào):3D視覺(jué)工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    使用CUDA并行化矩陣乘法加速Blender Python

      這篇文章描述了兩種不同的加速矩陣乘法的方法。第一種方法使用 Numba 編譯器來(lái)減少 Python 代碼中與循環(huán)相關(guān)的開(kāi)銷。第二種方法使用 CUDA 并行化矩陣
    的頭像 發(fā)表于 04-24 17:04 ?5427次閱讀
    使用<b class='flag-5'>CUDA</b>并行化<b class='flag-5'>矩陣</b><b class='flag-5'>乘法</b>加速Blender Python

    解析優(yōu)化的調(diào)度邏輯和cuda實(shí)現(xiàn)

    的梯度上,所有這些都在一個(gè)操作中完成,可以避免多次訪問(wèn)global memory提升算子的帶寬。下面解析一下這個(gè)優(yōu)化的調(diào)度邏輯和cuda實(shí)現(xiàn)。 https://github.com/BBuf
    的頭像 發(fā)表于 08-24 11:15 ?1258次閱讀

    請(qǐng)問(wèn)C6748的DSPLIB中有double型矩陣乘法函數(shù)嗎?

    我用的板子是6748,想對(duì)矩陣乘法進(jìn)行優(yōu)化,但發(fā)現(xiàn)674X 各個(gè)版本的DSPLIB里函數(shù)沒(méi)有dp的。是因?yàn)門(mén)I公司還沒(méi)有開(kāi)發(fā)相應(yīng)的函數(shù)嗎?還是因?yàn)槲覜](méi)有找到呢?期待回復(fù),謝謝!
    發(fā)表于 07-25 07:56

    講解矩陣運(yùn)算中的放縮,乘法和轉(zhuǎn)置

    第22章 DSP矩陣運(yùn)算-放縮,乘法和轉(zhuǎn)置矩陣本期教程主要講解矩陣運(yùn)算中的放縮,乘法和轉(zhuǎn)置。目錄第22章 DSP
    發(fā)表于 08-11 06:05

    主要講解矩陣運(yùn)算中的放縮,乘法和轉(zhuǎn)置

    第22章 DSP矩陣運(yùn)算-放縮,乘法和轉(zhuǎn)置矩陣本期教程主要講解矩陣運(yùn)算中的放縮,乘法和轉(zhuǎn)置。目錄第22章 DSP
    發(fā)表于 08-11 08:41

    原碼乘法,原碼乘法原理詳解

    原碼乘法,原碼乘法原理詳解   1.人工算法與機(jī)器算法的同異性    在定點(diǎn)計(jì)算機(jī)中,兩個(gè)原碼表示的數(shù)相乘的運(yùn)算規(guī)則是:乘積的符號(hào)位由兩數(shù)的
    發(fā)表于 04-13 10:55 ?3.3w次閱讀

    補(bǔ)碼一位乘法原理詳解

    補(bǔ)碼一位乘法原理詳解
    發(fā)表于 04-13 14:12 ?1.6w次閱讀
    補(bǔ)碼一位<b class='flag-5'>乘法</b>原理<b class='flag-5'>詳解</b>

    支持優(yōu)化分塊策略的矩陣乘加速器

    在許多應(yīng)用領(lǐng)域中,大規(guī)模浮點(diǎn)矩陣乘法往往是最耗時(shí)的計(jì)算核心之一。在新興的應(yīng)用中經(jīng)常存在至少有一個(gè)維度很小的大規(guī)模矩陣,我們把具備這種特性的矩陣稱為非均勻
    發(fā)表于 11-25 10:38 ?3次下載
    支持<b class='flag-5'>優(yōu)化</b>分塊策略的<b class='flag-5'>矩陣</b>乘加速器

    Adreno GPU 矩陣乘法——第1講:OpenCL優(yōu)化

    文章中的概念和下一篇文章中的OpenCL代碼清單,表示Adreno 4xx和5xx GPU系列設(shè)備端矩陣乘法內(nèi)核函數(shù)和主機(jī)端參考代碼的優(yōu)化實(shí)現(xiàn)。我們希望本系列文章將幫助和鼓勵(lì)您使用這些想法和代碼示例寫(xiě)出
    發(fā)表于 09-18 19:15 ?1753次閱讀

    使用英特爾數(shù)學(xué)核心函數(shù)庫(kù)優(yōu)化三重嵌套循環(huán)矩陣乘法

    我們使用英特爾?數(shù)學(xué)核心函數(shù)庫(kù)(MKL)在Linux *上優(yōu)化了三重嵌套循環(huán)矩陣乘法的版本。
    的頭像 發(fā)表于 11-07 06:04 ?3535次閱讀

    基于深度學(xué)習(xí)的矩陣乘法加速器設(shè)計(jì)方案

    為滿足深度學(xué)習(xí)推理中對(duì)不同規(guī)模矩陣乘法的計(jì)算需求,提出一種基于 Zynq soc平臺(tái)的整數(shù)矩陣乘法加速器。采用基于總線廣播的并行結(jié)構(gòu),充分利用片上數(shù)據(jù)的重用性并最小化中間累加結(jié)果的移動(dòng)
    發(fā)表于 05-25 16:26 ?3次下載

    深度學(xué)習(xí)中矩陣乘法計(jì)算速度再次突破

    n階矩陣乘法最優(yōu)解的時(shí)間復(fù)雜度再次被突破,達(dá)到了 。 按定義直接算的話,時(shí)間復(fù)雜度是O(n3)。 光這么說(shuō)可能不太直觀,從圖上可以看出,n足夠大時(shí)優(yōu)化后的算法就開(kāi)始表現(xiàn)出明顯優(yōu)勢(shì)。 矩陣
    的頭像 發(fā)表于 06-24 17:36 ?2560次閱讀
    深度學(xué)習(xí)中<b class='flag-5'>矩陣</b><b class='flag-5'>乘法</b>計(jì)算速度再次突破

    人工智能或可助力矩陣乘法運(yùn)算原理解析

    矩陣乘法是所有數(shù)學(xué)中最基本和最普遍的運(yùn)算之一。要將一對(duì) n×n 矩陣相乘,每個(gè)矩陣都有 n^2 個(gè)元素,你可以將這些元素以特定組合相乘并相加以生成乘積,即第三個(gè) n×n
    發(fā)表于 12-02 16:35 ?914次閱讀

    NVIDIA Hopper GPU上的新cuBLAS12.0功能和矩陣乘法性能

    NVIDIA Hopper GPU 上的新 cuBLAS 12.0 功能和矩陣乘法性能
    的頭像 發(fā)表于 07-05 16:30 ?2251次閱讀
    NVIDIA Hopper GPU上的新cuBLAS12.0功能和<b class='flag-5'>矩陣</b><b class='flag-5'>乘法</b>性能

    FPGA加速神經(jīng)網(wǎng)絡(luò)的矩陣乘法

    電子發(fā)燒友網(wǎng)站提供《FPGA加速神經(jīng)網(wǎng)絡(luò)的矩陣乘法.pdf》資料免費(fèi)下載
    發(fā)表于 09-15 14:50 ?0次下載
    FPGA加速神經(jīng)網(wǎng)絡(luò)的<b class='flag-5'>矩陣</b><b class='flag-5'>乘法</b>