2016-04-03 66 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