2017-02-16 41 views
0

ピアツーピアをサポートしていない(同じPCIルートハブにない)GPU用の古いAPIを使用して、異なるプロセスで2つのGPU間でデータをコピーしたいとします。しかし、私は同期に問題があります。私はそれらを理解して基本的な手順は以下のとおりです。cudaMemcpyPeerを使用して、P2Pを使用できない別のプロセスのGPU間でGPUデータをコピーするにはどうすればよいですか?

(プロセス0、デバイス0):

void * d_X; 
cudaMalloc(&d_X, size); 
// Put something into d_X; 
cudaIpcMemHandle_t data; 
cudaIpcGetMemHandle(&data, (void *)d_X); 

は - >/MPI_RECV

(プロセス1、デバイスMPI_Send関数を経由して1を処理するためのアドレスとサイズを送信します1):

cudaSetDevice(1); 
void * d_Y; 
cudaMalloc(&d_Y, size); 
cudaSetDevice(0); // Need to be on device 0 to copy from device 0 

void * d_X; 
cudaIpcOpenMemHandle(&d_X, data, cudaIpcMemLazyEnablePeerAccess); 
cudaMemcpyPeer(d_Y, 1, d_X, 0, size); 
cudaIpcCloseMemHandle(d_X); 

これは基本的に正しいですか?いったんこれが正しいアプローチだと確信すれば、同期の問題があることは明らかです(失効したメモリは基本的にはコピーされています)ので、正しく同期する方法を検討する必要があります。

私のGPUはUVAをサポートしていますが、cudaDeviceCanAccessPeerは0を返します。私は実際にP2Pとこれに対応するいくつかのコードを書こうとしていますが、これは問題です。

+2

あなたはcuda simpleIPCサンプルコードを勉強しましたか? –

+0

悲しいことに、それはP2Pのみのためであり、メモリをコピーしないので、私がやっていることが正しいかどうかについてあいまいさがあります。 –

答えて

2

あなたが求めていることは可能だとは思いません。

cudaIPCOpenMemHandledocumentationを読み込んだ場合(メモリハンドルを別のプロセスからローカルプロセスで使用可能なデバイスポインタに変換する必要があります)、唯一のフラグはcudaIpcMemLazyEnablePeerAccessです。ピアが可能でないデバイスでこのフラグを使ってこの呼び出しを実行すると、エラーが返されます(私のテストによれば、とにかくそれは明らかです)。

したがって、プロセスAでは、デバイスがピア対応可能でない限り(またはプロセスによって使用されているデバイスと同じデバイス上にない限り)、プロセスBのデバイス割り当てに使用可能なデバイスポインタを取得する方法はありませんA - これはthe cuda simpleIPC sample codeに示されている)。

プロセスBでデバイスからホストにデータをコピーし、通常のLinux IPCメカニズム(たとえば、simpleIPC sample codeに示すようにマップされたメモリ)を使用して、そのホストデータをプロセスAで使用できるようにするオプションがあります。必要に応じてプロセスAのデバイスにコピーすることができます。

同じプロセスの2つのデバイスの場合、これらの2つのデバイス間でP2Pが不可能な場合は、これは多少なりとも正確です。cudaMemcpyPeerfallbackモードでは、ホストステージングバッファを介してデータをコピーします。

+0

これはまさに私が得ようとしているものです - 私はcudaMemcpyPeerをこれらの条件のもとで正しく動作させようとしています。現時点では、いくつかの同期の問題のために古いメモリをコピーしたり、上書きする可能性があります。要点は、可能な唯一の方法であれば、CUDA APIを使用してステージングスルーホストメモリビットを実行することです。 –

+0

このために 'cudaMemcpyPeer'を使用することはできません。 –

+0

まあ...それは動作します。私はちょうど同期の問題があります。私が最初に実行すると、データが正しくコピーされます。 –

関連する問題