Потоки 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) из второго потока, но больше ничего не перекрывается.

У меня может не быть ресурсов для запуска двух ядер (я думаю, что есть), но, по крайней мере, выполнение и копирование ядра должны перекрываться, верно? И если я помещу все 3 (копирование H2D, выполнение ядра, копирование D2H) в один и тот же цикл for, ни один из них не перекроется...

ПОМОГИТЕ, из-за чего это может быть?

Я работаю:

Убунту 10.04 x64

Устройство: «GeForce GTX 460» (версия драйвера CUDA: 3.20, версия среды выполнения CUDA: 3.20, номер основной/дополнительной версии возможностей CUDA: 2.1, параллельное копирование и выполнение: да, параллельное выполнение ядра: да)


person pmcr    schedule 20.05.2011    source источник
comment
Механизм профилирования в CUDA при некоторых обстоятельствах вызывает сериализацию внутри потоков. Вы не можете использовать профилировщик для оценки перекрытия асинхронных операций API.   -  person talonmies    schedule 20.05.2011
comment
Спасибо. Есть ли другой способ узнать наверняка, правильно ли перекрытие? Судя по таймингам - нет...   -  person pmcr    schedule 20.05.2011


Ответы (2)


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

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

person tpm1510    schedule 20.05.2011

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

person shadow    schedule 14.08.2012
comment
Действительно ли возможно наблюдать перекрытие потоков непосредственно с помощью Visual Profiler 5.0? Если да, то как? В настоящее время я использую профилировщик командной строки и импортирую созданный файл .csv в профилировщик, см. Публикация NVIDIA о перекрывающихся потоках. - person Vitality; 06.06.2013