Первый вызов clEnqueueMapBuffer занимает много времени - PullRequest
0 голосов
/ 12 ноября 2018

У меня проблема с производительностью при внедрении YOLO для кода OpenCL.

Метод, который просто извлекает данные с устройства, работает медленно и быстро после нескольких вызовов.Есть журнал с вызовами, время в микросекундах:

clEnqueueMapBuffer      144469
memcpy  2
clEnqueueUnmapMemObject 31
clEnqueueMapBuffer      466
memcpy  103
clEnqueueUnmapMemObject 14
clEnqueueMapBuffer      468
memcpy  106
clEnqueueUnmapMemObject 17

Первый вызов с 1-байтовой копией (где memcpy занимает 2 микросекунды).

Память выделяется кодом:

if (!x)
    x = (float*) calloc(n, sizeof(float));

buf.ptr = x;

cl_int clErr;
buf.org = clCreateBuffer(opencl_context, CL_MEM_READ_WRITE | 
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, buf.len * buf.obs, buf.ptr, &clErr);

Код для извлечения данных следующий:

#ifdef BENCHMARK
    clock_t t;
    double time_taken;
    t = clock();
#endif
    cl_int clErr;
    void* map = clEnqueueMapBuffer(opencl_queues[opencl_device_id_t], x_gpu.mem, CL_TRUE, CL_MAP_READ,
                                   0, x_gpu.len * x_gpu.obs, 0, NULL, NULL, &clErr);
#ifdef BENCHMARK
    t = clock() - t;
    time_taken = ((double)t);
    printf("clEnqueueMapBuffer\t%d\n", (int)time_taken);
    t = clock();
#endif
    if (clErr != CL_SUCCESS)
        printf("could not map array to device. error: %s\n", clCheckError(clErr));
    memcpy(x, map, (n - x_gpu.off) * x_gpu.obs);
#ifdef BENCHMARK
    t = clock() - t;
    time_taken = ((double)t);
    printf("memcpy\t%d\n", (int)time_taken);
    t = clock();
#endif
    clErr = clEnqueueUnmapMemObject(opencl_queues[opencl_device_id_t], x_gpu.mem, map, 0, NULL, NULL);
    if (clErr != CL_SUCCESS)
        printf("could not unmap array from device. error: %s\n", clCheckError(clErr));
#ifdef BENCHMARK
    t = clock() - t;
    time_taken = ((double)t);
    printf("clEnqueueUnmapMemObject\t%d\n", (int)time_taken);
#endif

Что может быть причиной такой задержки во время первого вызова?Как уменьшить задержку?

1 Ответ

0 голосов
/ 12 ноября 2018

Ваш clEnqueueMapBuffer() вызов блокируется (CL_TRUE для параметра blocking_map), что означает, что вызов будет возвращен только после того, как операция преобразования завершит , завершенную .Если ваша очередь команд не является параллельной, любые ранее помещенные в очередь асинхронные команды, такие как ядра в очереди, должны быть завершены, прежде чем отображение может даже начаться .Если есть такие более ранние команды, вы фактически измеряете их завершение, а также операцию отображения памяти.Чтобы избежать этого, добавьте clFinish() звонок перед запуском часов.(Возможно, чуть более эффективно не для вызова clFinish(), поэтому я рекомендую оставить его только для целей измерения.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...