最初に、私は 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_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
古い GPU の制限は 65535 ではありませんか? x グリッド ディメンションの 65535 バリアを超えると、GPU が「台無し」になるのはなぜですか? それともこれは設計によるものですか?世界で何が起こっているのですか?
うわー、長い質問で申し訳ありません。
これを理解するための助けがあれば大歓迎です! ありがとう!