2017-02-16 5 views
0

Я хочу скопировать данные между двумя графическими процессорами в разных процессах, используя старый API для графических процессоров, которые не поддерживают одноранговый (они не находятся в одном корневом концентраторе PCI). Однако у меня возникают проблемы с синхронизацией. Основные шаги, как я их понимаю, являются:Как использовать cudaMemcpyPeer для копирования данных GPU между GPU в разных процессах, которые не могут использовать P2P?

(процесс 0, устройство 0):

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

-> Отправить адрес и размер Обработать 1 через MPI_Send/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); 

Это в основном правильно? Как только я уверен, что это правильный подход, мне нужно правильно разобраться, как правильно синхронизироваться, потому что ясно, что у меня проблемы с синхронизацией (в основном, копирование старой памяти).

Мои графические процессоры поддерживают UVA, но cudaDeviceCanAccessPeer возвращает 0. Я на самом деле пытаюсь написать код, который работает как для P2P, так и для этого, но это бит, с которым у меня проблемы.

+2

Вы изучили образец кода cuda simpleIPC? –

+0

К сожалению, это только для P2P, и он не копирует память, поэтому есть двусмысленность относительно того, правильно ли я делаю. –

ответ

2

Я не думаю, что то, о чем вы просите, возможно.

Если вы читали documentation для cudaIPCOpenMemHandle (что было бы необходимо в любом случае, чтобы преобразовать дескриптор памяти от другого процесса в указатель устройства, используемого в локальном процессе), единственный возможный флаг cudaIpcMemLazyEnablePeerAccess. Если вы запустите этот вызов с этим флагом на устройствах, которые не поддерживают одноранговую систему, он вернет ошибку (согласно моему тестированию, и это должно быть довольно очевидным в любом случае).

Таким образом, в процессе A нет способа получить полезный указатель устройства для распределения устройства в процессе B, если только устройства не являются одноранговыми (или если оно не находится на том же устройстве, что и тот, который используется процессом A - что показано в the cuda simpleIPC sample code).

Опцией "fallback" является копирование данных с устройства на хост в процессе B и использование обычных механизмов IPC Linux (например, сопоставленная память, как показано в simpleIPC sample code), чтобы сделать данные хоста доступными в процессе A. От там вы можете скопировать его на устройство в процессе A, если хотите.

Хотя это кажется утомительным, это более или менее точно то, что делает cudaMemcpyPeer для двух устройств в том же процессе, когда P2P невозможен между этими двумя устройствами. Режим fallback предназначен для копирования данных через буфер промежуточного хоста.

+0

Отлично, это именно то, что я пытаюсь получить - я пытаюсь заставить cudaMemcpyPeer вести себя правильно в этих условиях. В настоящий момент он продолжает копировать устаревшую память или, возможно, перезаписывать ее из-за некоторой проблемы синхронизации. Все дело в том, что я должен использовать API CUDA для выполнения бит промежуточной памяти, если это единственный способ. –

+0

Вы не сможете использовать 'cudaMemcpyPeer' для этого. –

+0

Ну ... это работает. У меня просто проблема синхронизации. При первом запуске он копирует данные правильно. –

Смежные вопросы