NVIDIA が提供する豊富なドキュメントに注目してください。
プログラミングガイドから:
float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));
これは、メモリを割り当てる方法の簡単な例です。さて、カーネルでは、次のように float へのポインターを受け入れる必要があります。
__global__
void kernel1(float *some_neat_data)
{
some_neat_data[threadIdx.x]++;
}
__global__
void kernel2(float *potentially_that_same_neat_data)
{
potentially_that_same_neat_data[threadIdx.x] *= 0.3f;
}
したがって、次のように呼び出すことができます。
float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));
kernel1<<<1,128>>>(devPtr);
kernel2<<<1,128>>>(devPtr);
このデータは多くの機能で使用されるため、グローバル化してほしいと考えています。
グローバルを使用する正当な理由はほとんどありません。これは間違いなく一つではありません。「devPtr」をグローバル スコープに移動することを含めて、この例を拡張する演習として残します。
編集:
わかりました、根本的な問題はこれです: カーネルはデバイス メモリにしかアクセスできず、使用できる唯一のグローバル スコープ ポインターは GPU のものです。CPU からカーネルを呼び出すと、裏で、カーネルが実行される前にポインタとプリミティブが GPU レジスタや共有メモリにコピーされます。
したがって、私が提案できる最も近いものはこれです: cudaMemcpyToSymbol() を使用して目標を達成してください。しかし、バックグラウンドでは、別のアプローチが正しいことである可能性があることを考慮してください。
#include <algorithm>
__constant__ float devPtr[1024];
__global__
void kernel1(float *some_neat_data)
{
some_neat_data[threadIdx.x] = devPtr[0] * devPtr[1];
}
__global__
void kernel2(float *potentially_that_same_neat_data)
{
potentially_that_same_neat_data[threadIdx.x] *= devPtr[2];
}
int main(int argc, char *argv[])
{
float some_data[256];
for (int i = 0; i < sizeof(some_data) / sizeof(some_data[0]); i++)
{
some_data[i] = i * 2;
}
cudaMemcpyToSymbol(devPtr, some_data, std::min(sizeof(some_data), sizeof(devPtr) ));
float* otherDevPtr;
cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));
kernel1<<<1,128>>>(otherDevPtr);
kernel2<<<1,128>>>(otherDevPtr);
return 0;
}
この例では、'--host-compilation=c++' を忘れないでください。