簡體   English   中英

CUDA:在共享內存上移動數組

[英]CUDA: Shift arrays on shared memory

我試圖將扁平的2D矩陣加載到共享內存中,沿x移位數據,沿y回寫到全局內存移位。 因此輸入數據沿x和y移動。 我有的:

__global__ void test_shift(float *data_old, float *data_new)

{

uint glob_index = threadIdx.x + blockIdx.y*blockDim.x;

__shared__ float VAR;
__shared__ float VAR2[NUM_THREADS];

// load from global to shared

VAR = data_old[glob_index];

// do some stuff on VAR 

if (threadIdx.x < NUM_THREADS - 1)
{
VAR2[threadIdx.x + 1] = VAR; // shift (+1) along x
}

__syncthreads();

// write to global memory

if (threadIdx.y < ny - 1)
{
glob_index = threadIdx.x + (blockIdx.y + 1)*blockDim.x; // redefine glob_index to shift along y (+1)
data_new[glob_index] = VAR2[threadIdx.x];
}

對內核的調用:

test_shift <<< grid, block >>> (data_old, data_new);

和網格和塊(blockDim.x等於矩陣寬度,即64):

dim3 block(NUM_THREADS, 1);
dim3 grid(1, ny); 

我無法實現它。 有人可以指出這有什么問題嗎? 我應該使用跨步索引還是偏移量?

VAR不應該被聲明為共享,因為在當前形式中,當您從全局內存加載時,所有線程都會遍歷彼此的數據: VAR = data_old[glob_index];

當你訪問VAR2[threadIdx.x + 1] ,你也有一個越界訪問,所以你的內核永遠不會完成(取決於設備的計算能力 - 1.x設備沒有嚴格檢查共享內存訪問)。

您可以通過檢查所有CUDA函數調用的返回碼來檢測后者是否有錯誤。

共享變量由單個塊中的所有線程共享。 這意味着您沒有blockDim.y對共享變量的補充,但每個塊只有一個complect。

uint glob_index = threadIdx.x + blockIdx.y*blockDim.x;

__shared__ float VAR;
__shared__ float VAR2[NUM_THREADS];
VAR = data_old[glob_index];

if (threadIdx.x < NUM_THREADS - 1)
{
  VAR2[threadIdx.x + 1] = VAR; // shift (+1) along x
}

這指示塊中的所有線程將數據寫入單個變量(VAR)。 接下來,您沒有同步,並在第二個分配中使用此變量。 這將有未定義的結果,因為來自第一個warp的線程正在讀取此變量,而來自第二個warp的線程仍在嘗試在那里寫入某些內容。 您應該將VAR更改為本地,或者為塊中的所有線程創建共享內存變量數組。

if (threadIdx.y < ny - 1)
{
  glob_index = threadIdx.x + (blockIdx.y + 1)*blockDim.x; 
  data_new[glob_index] = VAR2[threadIdx.x];
}

在VAR2 [0]中你仍然有一些垃圾(你從來沒有寫過)。 threadIdx.y在您的塊中始終為零。

並避免使用uints。 他們有(或曾經有)一些性能問題。

實際上,對於這樣簡單的任務,您不需要使用共享內存

__global__ void test_shift(float *data_old, float *data_new)
{

int glob_index = threadIdx.x + blockIdx.y*blockDim.x;

float VAR;

// load from global to local
VAR = data_old[glob_index];

int glob_index_new;
// calculate only if we are going to output something
if ( (blockIdx.y < gridDim.y - 1) && ( threadIdx.x < blockDim.x - 1 ))
{
  glob_index_new = threadIdx.x + 1 + (blockIdx.y + 1)*blockDim.x;

  // do some stuff on VAR 
} else // just write 0.0 to remove garbage
{
  glob_index_new = ( (blockIdx.y == gridDim.y - 1) && ( threadIdx.x == blockDim.x - 1 ) ) ? 0 : ((blockIdx.y == gridDim.y - 1) ? threadIdx.x : (blockIdx.y)*blockDim.x );
  VAR = 0.0;
} 

// write to global memory

data_new[glob_index_new] = VAR;
}

暫無
暫無

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

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