[英]Does launching more CUDA thread blocks have more overhead than launching fewer?
[英]CUDA and thread blocks overhead
我已經實現了一個計算矩陣乘法的簡單內核。 這是代碼:
__global__ void MatMultKernel(Mat A, Mat B, Mat C){
int i;
double val=0.0;
int ix=blockDim.x*blockIdx.x+threadIdx.x;
int iy=blockDim.y*blockIdx.y+threadIdx.y;
if(ix<A.nrows && iy<B.nrows){
for(i=0;i<A.nrows;i++)
val+=A.value[iy*A.nrows+i]*B.value[i*B.nrows+ix];
C.value[iy*C.nrows+ix]=val;
}
}
我通過改變線程和塊配置來測量這個內核的運行時間。
如果線程在列塊中分配(例如dim3(1,256,1)),我看到執行時間總是更糟糕。這是什么原因?
首先,我要指出您的代碼僅適用於方形矩陣,通常您應該在代碼的所有三個位置使用A.ncols
而不是A.nrows
。
性能差異是由於內存訪問。 你必須存儲在行主要格式的所有三個矩陣和代碼執行以下操作:每個線程訪問iy
的排第A
和ix
的列處B
,並計算它們的點積。 請注意,warp中的所有線程總是同時執行相同的指令,因此在代碼中的串行循環中,對於warp中的所有線程, i
總是相同的。 在您的代碼中,塊形狀很重要,因為:
(256, 1, 1)
,則塊中的每個線程具有相同的iy
,但是ix
不同。 讓我們看一下B
的訪問模式:同一個warp中的所有線程總是訪問B
的同一行,因為在B.value[i*B.nrows+ix]
中i
是相同的而且ix
不同,所以負載可以合並 。 (1, 256, 1)
,則情況會被轉置,因此您可能希望合並來自A
的負載。 但事實並非如此,因為iy
確定了行,並且兩個相鄰線程訪問的值被A.ncols
偏移。 到接入圖案C
是一樣的B
,但較不重要。 對於2D塊,情況介於兩個1D案例之間。
如果要進一步優化代碼,可以使用“ CUDA編程指南”中所示的共享內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.