あなたの3つの質問に対する簡単な答えは次のとおりです。
- はい。
- はい (コードが 64 ビット ホスト オペレーティング システム用にコンパイルされている場合)。デバイス ポインターのサイズは、常に CUDA のホスト アプリケーションのポインター サイズと一致します。
- いいえ。
ポイント 3 を拡張するには、次の 2 つの単純なメモリ コピー カーネルを検討してください。
__global__
void debunk(float *in, float *out, int n)
{
int i = n * (threadIdx.x + blockIdx.x*blockDim.x);
for(int j=0; j<n; j++) {
out[i+j] = in[i+j];
}
}
__global__
void debunk2(float *in, float *out, int n)
{
int i = n * (threadIdx.x + blockIdx.x*blockDim.x);
float *x = in + i;
float *y = out + i;
for(int j=0; j<n; j++, x++, y++) {
*x = *y;
}
}
あなたの推測では、ローカル整数変数が 2 つしかないのに対し、追加のポインターが 2 つあるため、使用するレジスターを少なくするdebunk
必要があります。debunk2
それでも、CUDA 5 リリース ツールチェーンを使用してそれらをコンパイルすると、次のようになります。
$ nvcc -m64 -arch=sm_20 -c -Xptxas="-v" pointer_size.cu
ptxas info : 0 bytes gmem
ptxas info : Compiling entry function '_Z6debunkPfS_i' for 'sm_20'
ptxas info : Function properties for _Z6debunkPfS_i
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 8 registers, 52 bytes cmem[0]
ptxas info : Compiling entry function '_Z7debunk2PfS_i' for 'sm_20'
ptxas info : Function properties for _Z7debunk2PfS_i
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 8 registers, 52 bytes cmem[0]
それらはまったく同じレジスター数にコンパイルされます。ツールチェーンの出力を逆アセンブルすると、セットアップ コードを除けば、最終的な命令ストリームはほぼ同じであることがわかります。これにはいくつかの理由がありますが、基本的には次の 2 つの単純なルールに帰着します。
- C コード (または PTX アセンブラー) からレジスター数を決定しようとしても、ほとんど無駄です。
- 非常に洗練されたコンパイラとアセンブラを推測しようとしても、ほとんど無駄です。