這裏我的想法是,只有必要的線程/塊(每個線程掉期轉置矩陣的方形部分的方形子的兩個條目矩陣),然後遍歷並轉置剩餘的條目。
__global__ void kernelTranspuesta(float *a, float *c, int m, int n) {
int i = threadIdx.x + blockIdx.x*blockDim.x;
int j = threadIdx.y + blockIdx.y*blockDim.y;
int smallest = M < N ? M : N;
while(j < smallest){
i = threadIdx.x + blockIdx.x*blockDim.x;
while(i < j){
c[i*m+j] = a[j*n+i];
c[j*m+i] = a[i*n+j];
i+= blockDim.x*gridDim.x;
}
if(i == j)
c[j*m+i] = a[i*n+j];
j+= blockDim.y*gridDim.y;
}
if(M > N) {
i = threadIdx.x + blockIdx.x*blockDim.x + N;
j = threadIdx.y + blockIdx.y*blockDim.y;
while(i < M){
j = threadIdx.y + blockIdx.y*blockDim.y;
while(j < N){
c[j*m+i] = a[i*n+j];
j+= blockDim.y*gridDim.y;
}
i+= blockDim.x*gridDim.x;
}
}else{
i = threadIdx.x + blockIdx.x*blockDim.x;
j = threadIdx.y + blockIdx.y*blockDim.y + M;
while(i < M){
j = threadIdx.y + blockIdx.y*blockDim.y + M;
while(j < N){
c[j*m+i] = a[i*n+j];
j+= blockDim.y*gridDim.y;
}
i+= blockDim.x*gridDim.x;
}
}
}
內核調用
dim3 hilos(16,16); // hilos(blockDim.x, blockDim.y)
dim3 bloques(8,8); // bloques(gridDim.x, gridDim.y)
kernelTranspuesta<<<bloques, hilos>>>(aD, cD, m, n);
我測試了512x256和256×512個矩陣,讓我知道你在想什麼。
爲什麼「可能很糟糕」 - 你有沒有基準測試內核?它達到峯值存儲帶寬的多少部分? – talonmies 2012-07-17 11:35:34
可能很糟糕,因爲我以前沒有測試過它。 Profiler報告27GB/s寫入吞吐量和5.3GB/s讀取。 – illumi 2012-07-17 12:44:37
可能最好在塊中讀入共享內存,進行轉置並寫入塊。你在這裏的寫作完全沒有合併。 – 2012-07-17 19:57:26