unsigned __int64
(スタックに 8 バイト) を割り当て、cudaHostRegister を使用してそのメモリを GPU に登録しようとする単純なプログラムがあります。この呼び出しを行うプログラムのセクションを以下に示します。
unsigned __int64 mem;
unsigned __int64 *pMem = &mem;
cudaError_t result;
result = cudaHostRegister(pMem, sizeof(unsigned __int64), cudaHostRegisterMapped);
if(result != cudaSuccess) {
printf("Error in cudaHostRegister: %s.\n", cudaGetErrorString(result));
return -1;
}
nvcc フラグの compute_11 と sm_11 を使用して Visual Studio 2010 Premium でコンパイルしています。すべてが cuda 機能バージョン 3.0 の Quadro K1000m を実行しているラップトップで正しく動作します。
最近、デスクトップに切り替えて、GeForce 8600 GT と GeForce 9500 GT で実行してみました。どちらも cuda 機能のバージョンは 1.1 です。
cudaHostRegister に関する NVIDIA のドキュメントによると、cuda 機能が 1.1 以上のカードでは、cudaHostRegisterMapped を使用できるはずです。
cudaHostRegisterMapped: 割り当てを CUDA アドレス空間にマップします。メモリへのデバイス ポインタは、cudaHostGetDevicePointer() を呼び出すことによって取得できます。この機能は、計算能力が 1.1 以上の GPU でのみ使用できます。
いくつかの検索の後、cudaHostRegisterMapped にはページ アライン メモリが必要なようです。これが私の 3.0 カードと 1.1 カードの違いかもしれないと考えたので、以下に示すように、アドレスをマスキングしてページ整列アドレスを取得し、サイズ フィールドでページのサイズ (4096 バイト) を使用しました。
unsigned __int64 mem;
unsigned __int64 *pMem = &mem;
unsigned __int64 memAddr = (unsigned __int64)pMem;
cudaError_t result;
pMem = (unsigned __int64 *)(memAddr & 0xFFFFFFFFFFFFF000);
result = cudaHostRegister(pMem, 4096, cudaHostRegisterMapped);
if(result != cudaSuccess) {
printf("Error in cudaHostRegister: %s.\n", cudaGetErrorString(result));
return -1;
}
このコードは 3.0 カードでも機能しますが、1.1 カードでは以前と同じ結果で失敗します。cudaHostRegister 関数は次のcudaErrorInvalidValue
ことを示すエラーを返します。
API 呼び出しに渡された 1 つ以上のパラメーターが許容範囲内の値ではありません
この関数がこのように失敗する理由については、これ以上見つけることができませんでした。誰でも提供できるヘルプをありがとう。
[編集] talonmies の応答に基づいて、少なくとも 1 つのカード (9500 GT、8600 GT では実行していません) が、SDK に付属する NVIDIA の deviceQuery 実行可能ファイルに従ってメモリ マッピングをサポートしていることを確認しました。