2013-06-25 76 views
0

Cuda的說,共享存儲器可以僅通過在相同的塊中的數據被共享。但一個塊最多隻能有1024個線程。如果我有一個巨大的矩陣,並希望以最大化的線程取平均值,該怎麼辦?超過塊取平均Cuda的

注意到此作爲一個例子。 (我沒有在一個塊中使用的最大的線程,只是作爲一個演示)

#include <iostream> 
#include <stdio.h> 

__global__ void 
kernel(int *a, int dimx, int dimy) 
{ 
int ix = blockDim.x * blockIdx.x + threadIdx.x; 
int iy = blockDim.y * blockIdx.y + threadIdx.y; 

int idx = iy * dimx + ix; 

__shared__ int array[64]; 

a[idx] = a[idx] + 1; 

array[idx] = a[idx]; 

__syncthreads(); 

int sum=0; 
for(int i=0; i<dimx*dimy; i++) 
{ 
    sum += array[i]; 
} 

int average = sum/(dimx*dimy+1.0f); 

a[idx] = average; 

} 

int 
main() 
{ 
int dimx = 8; 
int dimy = 8; 
int num_bytes = dimx*dimy*sizeof(int); 

int *d_a=0, *h_a=0; // device and host pointers 
h_a = (int*)malloc(num_bytes); 

for (int i=0; i < dimx*dimy; i++){ 
    *(h_a+i) = i; 
} 
cudaMalloc((void**)&d_a, num_bytes); 

//cudaMemset(d_a, 0, num_bytes); 

cudaMemcpy(d_a, h_a, num_bytes, cudaMemcpyHostToDevice); 

dim3 grid, block; 
block.x = 4; 
block.y = 4; 
grid.x = dimx/block.x; 
grid.y = dimy/block.y; 

kernel<<<grid, block>>>(d_a, dimx, dimy); 

cudaMemcpy(h_a, d_a, num_bytes, cudaMemcpyDeviceToHost); 


std::cout << "the array a is:" << std::endl; 
for (int row = 0; row < dimy; row++) 
{ 
    for (int col =0; col < dimx; col++) 
    { 
     std::cout << h_a[row * dimx + col] << " "; 
    } 
    std::cout << std::endl; 
} 

free(h_a); 
cudaFree(d_a); 
} 

我創建四個塊,並希望結果是平均所有這些的。現在的結果是:

the array a is: 
3 3 3 3 4 4 4 4 
3 3 3 3 4 4 4 4 
3 3 3 3 4 4 4 4 
3 3 3 3 4 4 4 4 
11 11 11 11 12 12 12 12 
11 11 11 11 12 12 12 12 
11 11 11 11 12 12 12 12 
11 11 11 11 12 12 12 12 

每個區塊都有自己的平均水平,而整體平均水平。我怎麼能把所有的塊的平均水平?

我新的CUDA技術。歡迎任何相關答案。

+1

看在CUDA SDK還原一個例子,看看這種事情做。 –

回答

1

最簡單的方法就是啓動多個內核,這樣你做你的每塊平均,寫那些出去全局內存,然後啓動另一個內核就從以前的內核中每塊的結果工作。根據您的數據維度,您可能需要重複多次。

例如(在僞代碼)

template <typename T> 
__global__ reduce(T* data, T* block_avgs) 
{ 
    //find the per-block average, write it out to block_avgs 
    //... 
} 

//in your caller: 
loop while you have more than 1 block: 
    call kernel using result from prev. iteration 
    update grid_dim and block_dim 

這是必要的,因爲有一個在CUDA沒有塊間的同步。你的問題是一個非常簡單的減少應用程序。看一下並行還原示例at the nvidia samples page以獲得更好的還原感。