OpenCL: слишком медленная передача асинхронных команд
Моя программа OpenCL (не пугайтесь, это автоматически сгенерированный код для 3D CFD) демонстрирует странное поведение - много времени тратится на процедуры opencl_enq_job_* (opencl_code.c), где используются только асинхронные команды OpenCL:
clEnqueueWriteBuffer(..,CL_FALSE,...,&event1);
clSetKernelArg(...);
...
clEnqueueNDRangeKernel(...,1,&event1,&event2);
clEnqueueReadBuffer(...,CL_FALSE,...,1,&event2,&event3);
clSetEventCallback(event3,...);
clFlush(...);
В выводе программы время, проведенное в opencl_enq_job_*, показывается как:
OCL отходы: 0,60456248727985751
Это означает, что 60% времени тратится на эти процедуры.
Большая часть времени (92%) проводится в функции clEnqueueReadBuffer и ~5% в clSetEventCallback.
Почему так много? Что не так в этом коде?
Моя конфигурация:
Platform: NVIDIA CUDA
Device 0: Tesla M2090
Device 1: Tesla M2090
Nvidia cuda_6.0.37 SDK and drivers.
Linux localhost 3.12.0 #6 SMP Thu Apr 17 20:21:10 MSK 2014 x86_64 x86_64 x86_64 GNU/Linux
Обновление: Nvidia приняла это как ошибку.
Обновление 1: на моем ноутбуке (MBP15, AMD GPU, Apple OpenCL) программа демонстрирует аналогичное поведение, но ожидает больше в clFlush (>99%). На CUDA SDK программа работает без clFlush, на программе Apple без clFlush зависает (отправленные задачи никогда не завершаются).
1 ответ
Я пробовал тоску по памяти, и это значительно улучшило ситуацию!
Проблема была решена.
Я думаю, что это не совсем ошибка; Я просто что-то пропустил в документации. Мои исследования привели меня к выводу, что драйвер просто не может выполнять асинхронную загрузку / сохранение не закрепленного буфера - даже если используются неблокирующие вызовы. Драйвер просто ждет возможности сохранить / загрузить данные, что может быть выполнено только после завершения задачи, и это нарушает параллелизм.