簡體   English   中英

3D矩陣求和

[英]Sum 3D matrix cuda

我需要進行如下計算:A [x] [y] = sum {從z = 0到z = n} {B [x] [y] [z] + C [x] [y] [z]},其中矩陣A的尺寸為[height] [width],矩陣B,C的尺寸為[height] [width] [n]。

值通過以下方式映射到內存:

index = 0;
for (z = 0; z<n; ++z)
    for(y = 0; y<width; ++y)
        for(x = 0; x<height; ++x) {
            matrix[index] = value;
            index++;
        }

Q1:這個Cuda內核可以嗎?

idx = blockIdx.x*blockDim.x + threadIdx.x;
idy = blockIdx.y*blockDim.y + threadIdx.y;

for(z=0; z<n; z++){
    A[idx*width+idy] += B[idx*width+idy+z*width*height] + C[idx*width+idy+z*width*height];
}

問題2:這是進行計算的較快方法嗎?

idx = blockIdx.x*blockDim.x + threadIdx.x;
idy = blockIdx.y*blockDim.y + threadIdx.y;
idz = blockIdx.z*blockDim.z + threadIdx.z;

int  stride_x = blockDim.x * gridDim.x;
int  stride_y = blockDim.y * gridDim.y;
int  stride_z = blockDim.z * gridDim.z;

while ( idx < height && idy < width && idz < n ) {
    atomicAdd( &(A[idx*width+idy]), B[idx*width+idy+idz*width*height] + C[idx*width+idy+idz*width*height] );
    idx += stride_x;
    idy += stride_y;
    idz += stride_z;
} 

第一個內核沒問題。 但是我們尚未合並對矩陣BC訪問。

至於第二內核功能。 您的數據競爭A[idx*width+idy]因為不僅有一個線程能夠寫入A[idx*width+idy]地址。 您需要其他同步,例如AttomicAdd

至於一般性問題:我認為實驗表明效果更好。 這取決於您擁有的典型矩陣大小。 請記住,Fermi <1024上的最大線程塊大小,並且如果矩陣的大小較大,則您會創建許多線程塊。 通常它比較慢(有很多線程塊)。

ArrayFire中真正簡單:

array A = randu(nx,ny,nz);
array B = sum(A,2); // sum along 3rd dimension
print(B);

Q1:用知道答案的矩陣進行測試

備注:使用非常大的矩陣時,您可能會遇到問題。 使用while循環以適當的增量。 與往常一樣,Cuda by Example是參考書。

可在此處找到實現嵌套循環的示例: 對於使用CUDA的嵌套循環 實施了while循環。

marina.k關於比賽條件是正確的。 由於原子操作會減慢代碼速度,因此這將更傾向於方法一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM