CUDA:达到 blockIdx.x 的最大可能值,用于计算能力 3.0

CUDA: Hitting the maximum possible value of blockIdx.x for compute capability 3.0

本文关键字:用于 计算 能力 blockIdx 达到 CUDA      更新时间:2023-10-16

首先,我应该说我对C++编程很陌生(更不用说CUDA(,尽管这是我大约184年前第一次学到的。我会说我有点与内存分配和数据类型大小脱节,尽管我正在学习。无论如何,这里是:

我有一个具有计算能力 3.0 的 GPU(它是带有 2GB DRAM 的 Geforce 660 GTX(。

通过 CUDA 示例中找到的 ./deviceQuery(以及我在网上找到的其他图表(,列出了我的最大网格大小:

Max dimension size of a grid size    (x,y,z): (2147483647, 65535, 65535)

在 2,147,483,647 (2^31-1( 处,x 维度很大,而且有点不错......然而,当我运行我的代码,在 x 维度上超过 65535 时,事情变得......奇怪。

我使用了Udacity课程中的一个例子,并对其进行了修改以测试极端情况。我保持内核代码相当简单来证明这一点:

__global__ void referr(long int *d_out, long int *d_in){
  long int idx = blockIdx.x;
  d_out[idx] = idx;
}

请注意,下面的ARRAY_SIZE是网格的大小,也是要对其进行操作的整数数组的大小。我将块的大小保留为 1x1x1。只是为了理解限制,我知道只有 1 个线程的块进行这么多操作是没有意义的,但我想了解网格大小限制是怎么回事。

int main(int argc, char ** argv) {
  const long int ARRAY_SIZE = 522744;
  const long int ARRAY_BYTES = ARRAY_SIZE * sizeof(long int);
  // generate the input array on the host
  long int h_in[ARRAY_SIZE];
  for (long int i = 0; i < ARRAY_SIZE; i++) {
    h_in[i] = i;
  }
  long int h_out[ARRAY_SIZE];
  // declare GPU memory pointers
  long int *d_in;
  long int *d_out;
  // allocate GPU memory
  cudaMalloc((void**) &d_in, ARRAY_BYTES);
  cudaMalloc((void**) &d_out, ARRAY_BYTES);
  // transfer the array to the GPU
  cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
  // launch the kernel with ARRAY_SIZE blocks in the x dimension, with 1 thread each.
  referr<<<ARRAY_SIZE, 1>>>(d_out, d_in);
  // copy back the result array to the CPU
  cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
  // print out the resulting array
  for (long int i =0; i < ARRAY_SIZE; i++) {
    printf("%li", h_out[i]);
    printf(((i % 4) != 3) ? "t" : "n");
  }
  cudaFree(d_in);
  cudaFree(d_out);
  return 0;
}

这在 MOST 65535 的 MOST ARRAY_SIZE下按预期工作。下面是输出的最后几行

65516   65517   65518   65519
65520   65521   65522   65523
65524   65525   65526   65527
65528   65529   65530   65531
65532   65533   65534

如果我将ARRAY_SIZE推到此之外,输出将变得非常不可预测,最终如果数字变得太高,我会收到一条Segmentation fault (core dumped)消息......不管这意味着什么。即。ARRAY_SIZE为 65536:

65520   65521   65522   65523
65524   65525   65526   65527
65528   65529   65530   65531
65532   65533   65534   131071

为什么现在说最后一个的blockIdx.x是131071??即 65535+65535+1。奇怪。

更奇怪的是,当我将ARRAY_SIZE设置为 65537 (65535+2( 时,输出的最后一行得到了一些非常奇怪的结果。

65520   65521   65522   65523
65524   65525   65526   65527
65528   65529   65530   65531
65532   65533   65534   131071
131072  131073  131074  131075
131076  131077  131078  131079
131080  131081  131082  131083
131084  131085  131086  131087
131088  131089  131090  131091
131092  131093  131094  131095
131096  131097  131098  131099
131100  131101  131102  131103
131104  131105  131106  131107
131108  131109  131110  131111
131112  131113  131114  131115
131116  131117  131118  131119
131120  131121  131122  131123
131124  131125  131126  131127
131128  131129  131130  131131
131132  131133  131134  131135
131136  131137  131138  131139
131140  131141  131142  131143
131144  131145  131146  131147
131148  131149  131150  131151
131152  131153  131154  131155
131156  131157  131158  131159
131160  131161  131162  131163
131164  131165  131166  131167
131168  131169  131170  131171
131172  131173  131174  131175
131176  131177  131178  131179
131180  131181  131182  131183
131184  131185  131186  131187
131188  131189  131190  131191
131192  131193  131194  131195
131196  131197  131198  131199
131200

65535 不是旧 GPU 的限制吗?为什么当我突破 x 网格维度的 65535 障碍时,我的 GPU "搞砸了"?还是这是设计使然?这到底是怎么回事?

哇,对不起,这个问题很长。

任何帮助理解这一点将不胜感激!谢谢!

您应该使用正确的 CUDA 错误检查 .并且,在使用 nvcc 进行编译时,您应该通过指定-arch=sm_30来针对计算 3.0 体系结构进行编译。