cuda矩陣相乘 CUDA的矩陣乘法

2021-10-12 23:22:03 字數 3518 閱讀 4426

(2)那麼下面就是不使用shared

memory的並行化演算法的思路。簡單地來說,就是將上述可並行化的部分傳遞給gpu,使用cuda來計算。**如下:

void matrixmulondevice(float*

m, float* n, float* p, intwidth)

int size = width * width * sizeof(float);

float* md,

nd,pd;

//設定呼叫核心函式時的執行緒數目

dim3 dimblock(width,

width);

dim3 dimgrid(1,

1);//在裝置儲存器上給m和n矩陣分配空間,並將資料複製到裝置儲存器中

cudamalloc(&md,

size);

cudamemcpy(md,

m, size, cudamemcpyhosttodevice);

cudamalloc(&nd,

size);

cudamemcpy(nd,

n, size, cudamemcpyhosttodevice);

//在裝置儲存器上給p矩陣分配空間

cudamalloc(&pd,

size);

//核心函式呼叫,將在後續部分說明

//只使用了乙個執行緒塊(dimgrid),此執行緒塊中有width*width個執行緒

matrixmulkernel<<

dimblock>>>(md,

nd,pd,width);

// 從裝置中讀取p矩陣的資料

cudamemcpy(p,

pd, size, cudamemcpydevicetohost);

// 釋放裝置儲存器中的空間

cudafree(md);

cudafree(nd);

cudafree (pd);

__global__ void matrixmulkernel(float*

md,float* nd,

float* pd, intwidth)

// 2維的執行緒id號

int tx = threadidx.x;

int ty = threadidx.y;

// pvalue用來儲存被每個執行緒計算完成後的矩陣的元素

float pvalue = 0;

//每個執行緒計算乙個元素

for(intk

= 0; k < width; ++k)

float

melement = md[ty

* width + k];

float

nelement = nd[k

* width + tx];

pvalue

+= melement * nelement;

// 將計算結果寫入裝置儲存器中

pd[ty*

width + tx]

= pvalue;

(3)這裡面有乙個很重要的問題就是所有的資料都放在了global

memory裡面,資料的傳輸速度會受到頻寬的限制,並且矩陣的大小受到計算能力的限制。所以可以將儲存器優化,演算法優化,使它更有效率地執行。

思路如下:

將整個大的width*width的矩陣分成tile_width*tile_width的小矩陣,一共可分為(width/tile_width)*(width/tile_width)個。當然此處要注意tile_width和計算能力的大小。

然後是將這些小矩陣分別進行計算,將計算結果放入shared

memory中,如上面的第二張圖。簡單來說就是m的藍色部分乘以n的藍色部分,結果放入黃色部分中;再用m的橙色部分乘以n的橙色部分,結果加入黃色部分中,依次類推。

定義blockspergrid和threadsperblock:

dim3

dimblock(tile_width,tile_width);

dim3

dimgrid(width/tile_width,width/tile_width);

呼叫核心函式:

matrixmulkernel<<>>(md,nd,pd,width);

核心函式如下:

__global__ void matrixmulkernel(float*

md,float* nd,

float* pd, intwidth)

//獲得執行緒塊號

intbx=

blockidx.x;

intby

= blockidx.y;

//獲得塊內的執行緒號

inttx=

threadidx.x;

intty=

threadidx.y;

//pvalue:執行緒計算完成後的子矩陣元素——自動變數

float pvalue = 0;

//迴圈,遍歷m和n的所有子矩陣

for (intm

= 0; m < width/tile_width; ++m)

//獲取指向當前矩陣m子矩陣的指標msub

float* mdsub =

getsubmatrix(md,m,by,width);

//獲取指向當前矩陣n的子矩陣的指標nsub

float* ndsub = getsubmatrix(nd,bx,m,width);

//共享儲存器空間宣告

__shared__ float mds[tile_width][tile_width];

__shared__ float nds和getmatrixelement(mdsub,tx,ty,width)【獲取子矩陣中某個元素的位址】的示意圖:

接下來是儲存結果:

//獲取指向矩陣p的子矩陣的指標

matrix psub

= getsubmatrix(p,bx,by);

//向全域性儲存器寫入執行緒塊計算後的結果子矩陣

//每個執行緒寫入乙個元素

setmatrixelement(psub,tx,ty,pvalue);

總的來說,核心函式的思路就是:

①獲得執行緒塊號以及塊內的執行緒號

②申明乙個自動變數以記錄執行緒計算完成之後的子矩陣元素

③從第乙個子矩陣開始,遍歷m和n的所有子矩陣,以完成如下操作:

④獲取指向當前矩陣m、n子矩陣的指標msub和nsub

⑤宣告兩個tile_width*tile_width大小的共享儲存器空間,分別對應m的子矩陣和n的子矩陣

⑥分別載入m和n的子矩陣的元素到共享儲存器中

⑦同步,確保所有的元素都已經載入共享儲存器中

⑧開始計算,每個執行緒計算執行緒塊內子矩陣的乙個元素

⑨同步,確保計算過程已經完成

⑩獲取指向矩陣p的子矩陣的指標

⑪向全域性儲存器中寫入計算結果後的子矩陣

但是小白現在還有乙個問題,按理說,pvalue應該是儲存在register中才對,那麼,向全域性儲存器中寫入計算結果的值是cuda自動從暫存器中取值然後再寫入嗎,但又有聽說register是不可定址的?所以表示不清楚,只好留待以後**吧。

CUDA矩陣相乘

include include include include 並行矩陣乘法kernel函式 global void matrixmultiply int m d,int n d,int p d,int width p d row width col p 每個執行緒計算p d矩陣的乙個元素 生成隨機...

CUDA系列三 矩陣相乘

本博文主要講解下基於cuda的矩陣相乘,cuda特別擅長的就是矩陣乘法,而且也比較容易實現。通過矩陣乘法的實現,可以比較容易理解cuda的核心思想。網上也有很多基於cuda實現的矩陣乘法,但是感覺都不完成,要不就是有錯,本文給出的 都是經過驗證可行的,希望能夠幫助到大家。矩陣乘法實現方式一 矩陣乘法...

CUDA 共享儲存器實現矩陣相乘

共享儲存器使用 shared 限定詞分配。cuda程式設計介面 執行初始化與裝置儲存器 cuda程式設計介面 使用nvcc編譯器的相容性 cuda程式設計介面 如何用nvcc編譯cuda程式 cuda程式設計模型 儲存器層次和異構程式設計 cuda程式設計模型 核心與執行緒層次概述 正如在前面的文章...