2016-04-03 63 views
1

模擬管道程序說我有兩個陣列ABkernel1,通過打破陣列成不同的組塊並執行兩個陣列上的一些計算(矢量相加例如)和寫入部分結果來Ckernel1然後繼續這樣做,直到處理數組中的所有元素。與CUDA

unsigned int i = blockIdx.x*blockDim.x + threadIdx.x; 
unsigned int gridSize = blockDim.x*gridDim.x; 

//iterate through each chunk of gridSize in both A and B 
while (i < N) { 
    C[i] = A[i] + B[i]; 
    i += gridSize; 
} 

說,現在我要發動對C一個kernel2和其他數據數組D。是否有反正我可以啓動kernel2馬上之後第一個塊在C是計算的嗎?實質上,kernel1管道它導致kernel2。依賴樹看起來像這樣

 Result 
    /\ 
     C D 
    /\  
    A B  

我曾想過使用CUDA流,但不知道究竟如何。也許在計算中包含主機?

回答

1

是的,您可以使用CUDA streams在這種情況下管理訂單和相關性。

我們假設您將要覆蓋複製和計算操作。這通常意味着您會將輸入數據分解爲「塊」,並且您會將塊複製到設備,然後啓動計算操作。每個內核啓動都在一個「大塊」數據上運行。

我們可以在主機代碼的循環管理過程:

// create streams and ping-pong pointer 
cudaStream_t stream1, stream2, *st_ptr; 
cudaStreamCreate(&stream1); cudaStreamCreate(&stream2); 
// assume D is already on device as dev_D 
for (int chunkid = 0; chunkid < max; chunkid++){ 
    //ping-pong streams 
    st_ptr = (chunkid % 2)?(&stream1):(&stream2); 
    size_t offset = chunkid*chunk_size; 
    //copy A and B chunks 
    cudaMemcpyAsync(dev_A+offset, A+offset, chksize*sizeof(A_type), cudaMemcpyHostToDevice, *st_ptr); 
    cudaMemcpyAsync(dev_B+offset, B+offset, chksize*sizeof(B_type), cudaMemcpyHostToDevice, *st_ptr); 
    // then compute C based on A and B 
    compute_C_kernel<<<...,*st_ptr>>>(dev_C+offset, dev_A+offset, dev_B+offset, chksize); 
    // then compute Result based on C and D 
    compute_Result_kernel<<<...,*st_ptr>>>(dev_C+offset, dev_D, chksize); 
    // could copy a chunk of Result back to host here with cudaMemcpyAsync on same stream 
    } 

頒發給同一個流的所有操作都保證,以便在設備上執行(即順序)。發佈給單獨流的操作可能會重疊。因此,上述序列應:

  • 拷貝A的組塊到設備
  • B的塊複製到設備
  • 發射內核來計算C來自A和B
  • 發射一個內核以計算來自C和D的結果

上述步驟將針對每個塊重複進行,但是會對替代流發出連續的塊操作。因此,塊2的複製操作可以與塊1的內核操作重疊等。

您可以通過查看CUDA流上的演示文稿來了解更多信息。 Here就是一個例子。

較新的設備(開普勒和麥克斯韋)應該相當靈活地瞭解設備上操作重疊所需的程序問題順序。較老的(費米)設備可能對發佈訂單敏感。你可以閱讀更多關於here