Перекрывающиеся передачи и выполнения ядра в CUDA с двумя циклами - PullRequest
0 голосов
/ 17 апреля 2020

Я хочу перекрывать передачу данных и выполнение ядра в такой форме:

int numStreams = 3;
int size = 10;

for(int i = 0; i < size; i++) {
    cuMemcpyHtoDAsync( _bufferIn1,
                           _host_memoryIn1 ),
                           _size * sizeof(T),
                           cuda_stream[i % numStreams]);

    cuMemcpyHtoDAsync( _bufferIn2,
                           _host_memoryIn2,
                           _size * sizeof(T),
                           cuda_stream[i % numStreams]);

        cuLaunchKernel( _kernel,
                        gs.x(), gs.y(), gs.z(),
                        bs.x(), bs.y(), bs.z(),
                        _memory_size,
                        cuda_stream[i % numStreams],
                        _kernel_arguments,
                        0
                      );
      cuEventRecord(event[i], cuda_stream);
}

for(int i = 0; i < size; i++) {
    cuEventSynchronize(events[i]);

    cuMemcpyDtoHAsync( _host_memoryOut,
                           _bufferOut,
                           _size * sizeof(T),
                           cuda_stream[i % numStreams]);
}

Возможно ли в этом случае перекрытие? В настоящее время только HtoD-переводы пересекаются с выполнением ядра. Первая передача DtoH выполняется после последнего выполнения ядра.

1 Ответ

2 голосов
/ 17 апреля 2020

Перекрытие возможно только тогда, когда операции выполняются в разных потоках. Операции CUDA в одном и том же потоке выполняются последовательно в соответствии с порядком вызова хоста, так что копия с устройства на хост в конце будет выполняться после завершения всех операций с соответствующими потоками. Перекрытие не происходит, потому что и последнее ядро, и первая копия выполняются в потоке 0, поэтому копия должна ждать, пока ядро ​​завершит sh. Поскольку вы синхронизируете с событием на каждой итерации l oop, другие копии в других потоках (поток 1 и 2) еще не вызываются.

...