Потоки CUDA не перекрываются
У меня есть что-то очень похожее на код:
int k, no_streams = 4;
cudaStream_t stream[no_streams];
for(k = 0; k < no_streams; k++) cudaStreamCreate(&stream[k]);
cudaMalloc(&g_in, size1*no_streams);
cudaMalloc(&g_out, size2*no_streams);
for (k = 0; k < no_streams; k++)
cudaMemcpyAsync(g_in+k*size1/sizeof(float), h_ptr_in[k], size1, cudaMemcpyHostToDevice, stream[k]);
for (k = 0; k < no_streams; k++)
mykernel<<<dimGrid, dimBlock, 0, stream[k]>>>(g_in+k*size1/sizeof(float), g_out+k*size2/sizeof(float));
for (k = 0; k < no_streams; k++)
cudaMemcpyAsync(h_ptr_out[k], g_out+k*size2/sizeof(float), size2, cudaMemcpyDeviceToHost, stream[k]);
cudaThreadSynchronize();
cudaFree(g_in);
cudaFree(g_out);
'h_ptr_in' и 'h_ptr_out' - это массивы указателей, выделенных с помощью cudaMallocHost (без флагов).
Проблема в том, что потоки не перекрываются. В визуальном профилировщике я вижу выполнение ядра из первого потока, перекрывающегося с копией (H2D) из второго потока, но больше ничего не перекрывается.
У меня может не быть ресурсов для запуска 2 ядер (я так думаю), но по крайней мере выполнение и копирование ядра должны перекрываться, верно? И если я помещу все 3 (копия H2D, выполнение ядра, копия D2H) в один и тот же цикл for, ни один из них не будет перекрываться...
ПОМОГИТЕ, пожалуйста, что может быть причиной этого?
Я бегу по:
Ubuntu 10.04 x64
Устройство: "GeForce GTX 460" (версия драйвера CUDA: 3.20, версия CUDA Runtime: 3.20, номер версии CUDA Capability Major/Minor: 2.1, одновременное копирование и выполнение: да, параллельное выполнение ядра: да)
2 ответа
Согласно этому сообщению на форумах NVIDIA, профилировщик будет сериализовать потоковую передачу для получения точных временных данных. Если вы считаете, что время выключено, убедитесь, что вы используете события CUDA...
В последнее время я экспериментировал с потоковой передачей и обнаружил, что пример simpleMultiCopy из SDK действительно полезен, особенно с соответствующей логикой и синхронизацией.
Если вы хотите, чтобы ядра перекрывались с ядрами (параллельными ядрами), вам нужно использовать CUDA Visual profiler 5.0, который поставляется с CUDA 5.0 Toolkit. Я не думаю, что предыдущие профилировщики способны на это. Также должно отображаться совпадение ядра и memcpy.