2013-05-31 31 views
4

我剛開始學習CUDA編程。我簡單地通過一些簡單的CUDA C例子,一切都在順風順水。然後!突然!推力!我認爲自己熟悉的C++函數子,並在差異CUDA CThrustCUDA C訴Thrust,我錯過了什麼?

之間嚇了一跳我覺得很難相信,

__global__ void square(float *a, int N) { 
    int idx = blockIdx.x * blockDim.x + threadIdx.x; 
    if (idx < N) { 
     a[idx] = a[idx] * a[idx]; 
    } 
} 

int main(int argc, char** argv) { 

float *aHost, *aDevice; 

const int N = 10; 
size_t size = N * sizeof(float); 

aHost = (float*)malloc(size); 
cudaMalloc((void**)&aDevice, size); 

for (int i = 0; i < N; i++) { 
    aHost[i] = (float)i; 
} 

cudaMemcpy(aDevice, aHost, size, cudaMemcpyHostToDevice); 

int block = 4; 
int nBlock = N/block + (N % block == 0 ? 0:1); 

square<<<nBlock, block>>>(aDevice, N); 

cudaMemcpy(aHost, aDevice, size, cudaMemcpyDeviceToHost); 

for (int i = 0; i < N; i++) { 
    printf("%d, %f\n", i, aHost[i]); 
} 

free(aHost); 
cudaFree(aDevice); 
} 

等同放着清單

template <typename T> 
    struct square { 
    __host__ __device__ T operator()(const T& x) const { 
     return x * x; 
    } 
}; 

int main(int argc, char** argv) { 
    const int N = 10; 
    thrust::device_vector<float> dVec(N); 
    thrust::sequence(dVec.begin(), dVec.end()); 
    thrust::transform(dVec.begin(), dVec.end(), dVec.begin(), square<float>()); 
    thrust::copy(dVec.begin(), dVec.end(), std::ostream_iterator<float>(std::cout, "\n")); 
} 

我缺少的東西?上面的代碼是否在GPU上運行? Thrust是一個很好的工具,但我懷疑它需要處理所有沉重的C風格內存管理。

  • Thrust代碼是否在GPU上執行?我怎麼知道?
  • Thrust如何消除喚起內核的奇怪語法?
  • Thrust實際上喚起了一個內核?
  • Thrust是否自動處理線程索引計算?

謝謝你的時間。很抱歉,如果這些都是愚蠢的問題,但是我發現我所看到的例子已經從可以被描述爲Model T到M3的瞬間立即轉變,我感到不可思議。

回答

6

粗略地說:是的,當然。 Thrust是一個圖書館,所有這些都是爲了讓它更容易而誕生。它的重點在於避免所有顯式的CUDA代碼,這對於其餘的程序員來說看起來很奇怪,它提供了一個友好的C++接口。

推力使用GPU,但不是只是 GPU。如果您編寫自己的代碼(即用於分配內存,複製,設置網格和塊大小的C/C++代碼),然後調用GPU執行內核,則會執行相同的操作。

對於那些不想進入低級別CUDA內部的人來說,這是一個很好的選擇,但是卻可以在簡單(但頻繁)的問題(如矢量操作)中利用GPU並行性。

+0

那麼'thrust :: transform'函數會喚起我的'方形內核?它如何知道如何分配線程? –

+2

是的,它調用你的* functor *,作爲*內核*的一部分,它創建「底層」。 Thrust是一個開源庫;你可以自己檢查一下。並且有GPU分析工具可以用來確認推力確實在使用GPU。關於線程的分配,在創建大量輸出時,CUDA編程中的一個常見策略是爲每個輸出元素分配一個線程。看看你的函子和整體算法,我發現輸入和輸出之間存在1:1的關係(通常是'transform'),所以每個數據元素有一個線程是有意義的。 –

相關問題