
GPUに転送できるデータは、cudaMallocHostで確保したメモリの内容だけでなく、newやmallocで確保したメモリの内容も含まれます。
その際ページロック(Page-Locked)をして、メモリ領域がページングされないようにしておくと、転送速度が大幅に早くなるので必ずやっておくようにしましょう。
ピンメモリ(Pinnedメモリ)と呼ばれる場合もありますが、同じものです。
なお、cudaMallocHost で確保されたメモリは既にページロックされているので、以下の操作は不要です。
ページロックの方法
ページロックをするには以下のAPIを使います。
API名 | 解説 |
cudaHostRegister | メモリ領域をページロック状態にします。 |
cudaHostUnregister | メモリ領域のページロック状態を解除します。 |
コード例
ページロックのコード例は以下の通りです。
new で確保した配列をページロックしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//配列サイズ int length = 512 * 1024 * 1024; size_t size = sizeof(int) * length; //2GB //ホストメモリの確保とページロック int* pHostSrc = new int[length]; cudaHostRegister(pHostSrc, size, cudaHostRegisterDefault); ... //ホストメモリのページロック解除と開放 cudaHostUnregister(pHostSrc); delete[] pHostSrc; |
転送速度の比較
ページロックしたときと、そうでないときの速度差を比較しました。
条件
・PCI-express Gen3
・転送データサイズ:2GB
・PCI-express Gen3
・転送データサイズ:2GB
条件 | 転送時間(msec) | 転送速度(GB/sec) |
ページロック有り | 179.0 | 11.4 |
ページロック無し | 407.7 | 5.0 |
なんと、ページロック有りと無しでは速度に2倍以上の差があることが判りました。
がんばってカーネルを高速化するよりも影響が大きいので、かならずページロック有りにしましょう。
ページロック有無の確認

NsightのTimelineで、転送部分にカーソルを合わせるとページロックがかかっているか見ることができます。
「Pinned」と表示されていたらページロックがかかっています。
なお、Nsightの見方は以下の記事で解説しています。

【CUDA】NsightのTimelineの使い方
CUDAでコーディングをしているとき、GPUで何が起きているか判らないですよね。
そんなときは、Nsightというツールを使って処理の解析をしましょう。
補足
速度面ではcudaMallocHostのほうが有利です。
cudaMallocHost ではメモリ領域確保と同時にページロックがされるので、特別な理由がない限りはわざわざcudaHostRegisterを使う必要はありません。
