Почему clGetPlatformInfo вызывается в каждой функции clEnqueue? - PullRequest
3 голосов
/ 07 мая 2020

Мы профилируем приложение OpenCL, работающее на графическом процессоре NVidia как на хосте, так и на устройстве. Мы были удивлены, обнаружив, что (на основе gperftools) хост проводил 44% своего времени в clGetPlatformInfo, методе, который вызывается только один раз в нашем собственном коде. Он вызывается clEnqueueCopyBuffer_hid, clEnqueueWriteBuffer_hid и clEnqueueNDRangeKernel_hid (и, предположительно, всеми другими clEnqueue методами, но они реже вызываются в нашем коде). Поскольку на это уходит так много времени нашего хоста, и мы, кажется, прямо сейчас связаны скоростью хоста, мне нужно знать, есть ли способ устранить эти лишние вызовы.

Почему это вызывается каждый вызов OpenCL? (Предположительно, это статическая c информация, которая может храниться в контексте?) Возможно, мы неправильно инициализировали наш контекст?

РЕДАКТИРОВАТЬ: Меня попросили указать MWE: MWE генерирует следующий профиль в течение нескольких секунд. Обратите внимание, что 99% времени тратится на clGetPlatformInfo. MWE Profile Results

Ответы [ 2 ]

0 голосов
/ 17 мая 2020

Мы выяснили проблему: gproftools с трудом давал правильную трассировку. Код на самом деле не вызывал clGetPlatformInfo тысячи раз, как сказал gperftools. Согласно беседе с bashbaug на форумах Khronos:

Когда я запускаю тест с gperftools с использованием нашего драйвера графического процессора, я вижу, что большую часть времени приписывается GTPin_Init, как вы упомянули. Я думаю, это связано с тем, что OpenCL ICD должен экспортировать очень мало символов, поскольку вызовы большинства API OpenCL происходят через таблицу отправки ICD.

Мы использовали предлагаемые им инструменты профилирования (OpenCL Intercept Layer, обнаруженный at https://github.com/intel/opencl-intercept-layer), чтобы лучше понять характеристики ядра во время выполнения и помочь нам найти некоторые утечки памяти. Это были утечки памяти, которые на самом деле вызвали замедление - кажется, что ядра долго запускаются, если им передается память с большим количеством ссылок в качестве аргументов.

Вы можете найти полный разговор на форумах Khronos здесь: https://community.khronos.org/t/why-does-clgetplatforminfo-get-called-in-every-clenqueue-function/105756/5

0 голосов
/ 08 мая 2020

Попробуйте передать NULL в качестве первого параметра clCreateContext. Идентификатор устройства уже передается, поэтому первый параметр, вероятно, не требуется и может вызвать эти дополнительные вызовы clGetPlatformInfo.

Еще одна вещь, которую нужно попробовать, - это связать с библиотекой OpenCL, отличной от Nvidia. Необязательно использовать библиотеку OpenCL от производителя графического процессора, любая из них должна работать, если используемые вами функции реализованы в этой другой библиотеке OpenCL. С Nvidia риска нет, потому что на сегодняшний день последней поддерживаемой версией является OpenCL 1.2, которую уже поддерживают большинство, если не все производители. Таким образом, вы можете попробовать OpenCL lib от других поставщиков SDK, таких как Intel или AMD. Если вы используете Ubuntu, вы можете использовать ocl-icd-opencl-dev.

====== ОБНОВЛЕНИЕ =========

Попробуйте указать платформу при создании контекста:

const cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties) platformId, 0}; 

cl_context context = clCreateContext (
    properties, // <-- here
    1,
    &deviceId,
    nullptr,
    nullptr,
    nullptr);

Может случиться так, что когда платформа не указана при создании контекста, тогда она будет запрашиваться каждый раз, когда это необходимо, но когда указано выше, это не будет.

...