Потоки 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 Версия исполнения: 3.20, Возможности CUDA. Основной/Малый номер версии: 2.1, Одновременная копия и исполнение: Да, Параллельное выполнение ядра: Да)

Ответ 1

Согласно этот пост на форумах NVIDIA, профилировщик будет сериализовать потоковое вещание, чтобы получить точные данные синхронизации. Если вы считаете, что ваши тайминги отключены, убедитесь, что вы используете события CUDA...

Я экспериментировал с потоковой передачей в последнее время, и я нашел пример "simpleMultiCopy" из SDK, чтобы быть действительно полезным, особенно с соответствующей логикой и синхронизацией.

Ответ 2

Если вы хотите совместить ядра с ядрами (параллельными ядрами), вам нужно использовать CUDA Visual profiler 5.0, который поставляется с CUDA 5.0 Toolkit. Я не думаю, что предыдущие профилографы способны на это. Он также должен показывать перекрытие ядра и memcpy.