2017-02-16 32 views
0

我想在不支持點對點的GPU(它們不在同一個PCI根集線器上)上使用舊的API API在不同進程中的兩個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_SEND爲流程1/MPI_RECV

(流程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

我不認爲你所要求的是可能的。

如果讀取documentationcudaIPCOpenMemHandle(這將是在任何情況下的存儲器句柄從另一個處理轉換成在本地過程中可使用的裝置指針必要),唯一可能的標誌爲cudaIpcMemLazyEnablePeerAccess。如果你在非對等功能的設備上使用此標誌運行此調用,它將返回一個錯誤(根據我的測試,無論如何它應該是非常明顯的)。

因此,在進程A中,無法獲得進程B中設備分配的可用設備指針,除非設備具有對等能力(或除非它與進程正在使用的設備在同一設備上) A - 在the cuda simpleIPC sample code中演示)。

「fallback」選項可以將數據從設備複製到進程B中的主機,並使用普通的Linux IPC機制(例如映射內存,如simpleIPC sample code中所示)使進程A中的主機數據可用。如果您願意,您可以將其複製到設備A中。

雖然這看起來很乏味,但對於同一過程中的兩臺設備,在兩臺設備之間無法使用P2P時,它幾乎完全是cudaMemcpyPeer所做的。 fallback模式是通過主機分段緩衝區複製數據。

+0

太棒了,這正是我想要得到的 - 我試圖讓cudaMemcpyPeer在這些條件下正確行爲。目前,由於一些同步問題,它一直在拷貝陳舊的內存,或者可能覆蓋它。整個過程對於我來說,如果這是唯一可行的方式,那麼我可以使用CUDA API來執行staging-through-host-memory位。 –

+0

您將無法爲此使用'cudaMemcpyPeer'。 –

+0

那麼......它的工作原理。我只是有一個同步問題。我第一次運行它時,它正確地複製了數據。 –