1

最初に、私は C++ でのプログラミング (CUDA は言うまでもなく) はまったくの初心者であると言わなければなりませんが、C++ は約 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;
}

これはARRAY_SIZE、65535 の at MOST で期待どおりに機能します。以下の出力の最後の数行

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_SIZE65536 の:

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

古い GPU の制限は 65535 ではありませんか? x グリッド ディメンションの 65535 バリアを超えると、GPU が「台無し」になるのはなぜですか? それともこれは設計によるものですか?世界で何が起こっているのですか?

うわー、長い質問で申し訳ありません。

これを理解するための助けがあれば大歓迎です! ありがとう!

4

1 に答える 1

6

適切な CUDA エラー チェックを使用する必要があります。-arch=sm_30また、いつ nvcc でコンパイルするかを指定して、コンピューティング 3.0 アーキテクチャ用にコンパイルする必要があります。

于 2013-10-03T13:54:19.453 に答える