为什么我们需要在CUDA内核中迈步?

时间:2017-10-04 11:54:25

标签: cuda

我想知道为什么需要在以下循环中使用grid-stride步幅:

for (int i = index; i < ITERATIONS; i =+ stride)
{
  C[i] = A[i] + B[i];
}

我们将步幅和索引设置为:

index = blockIdx.x * blockDim.x + threadIdx.x;
stride = blockDim.x * gridDim.x;

调用内核时我们有:

int blockSize = 5;
int ITERATIONS = 20;
int numBlocks = (ITERATIONS + blockSize - 1) / blockSize;
bench<<<numBlocks, blockSize>>>(A, B, C);

因此,当我们启动内核时,我们将拥有blockDim.x = 5和gridDim = 4,并且stride将等于20。

我的观点是,每当使用这种方法时,步幅总是等于或大于计算中元素的数量,因此每次增量循环都会结束。

这就是问题,为什么需要使用循环或步长,为什么不运行索引,像这样?:

index = blockIdx.x * blockDim.x + threadIdx.x;
C[index] = A[index] + B[index];

另一个问题是,在这个特殊情况下,我现在怎样才能同时在我的GPU上运行多少个线程,然后“跳转”到一个非常大的阵列的另一部分(例如2000000)?

1 个答案:

答案 0 :(得分:2)

  

我的观点是,每当使用这种方法时,步幅总是如此   等于或大于计算中的元素数,所以每个   它将会增加循环的时间将结束。

你的理解存在问题。要有效地使用该内核,您只需运行尽可能多的块,以实现设备的最大设备占用率,而不是处理所有数据所需的块数。那些较少的块然后变为“驻留”并且每个线程处理多个输入/输出对。网格跨度还保留了内核可能具有的任何内存合并和缓存一致性属性。

通过这样做,您可以消除调度和淘汰块的开销。通过这样做,简单内核可以获得相当大的效率提升。这种设计模式没有其他原因。