OpenCL clBuildProgram кэширует исходный код и не выполняет повторную компиляцию, если исходный код #include изменяется.

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

Я проверил другие сообщения в stackoverflow и увидел, что у nvidia есть серьезная проблема с передачей -I{include directory}, поэтому я изменил его и явно указал адрес файлов заголовков, но все же компилятор opencl не может найти ошибки в файле заголовка, который включен в имя файла ядра.

Кроме того, я использую nvidia gtx 980 и установил CUDA 7.0 на свой компьютер.

У кого-нибудь есть такой же опыт? как я могу это исправить?

Итак, предположим, что у меня есть такое ядро:

#include "../../src/cl/test_kernel_include.cl"

void __kernel test_kernel(
  __global int* result,
  int n
  )
{
  int thread_idx = get_global_id(0);
  result[thread_idx] = test_func();
}

который test_kernel_include.cl выглядит следующим образом:

int test_func()
{
  return 1;
}

Затем я запускаю код и получаю массив, все члены которого равны 1, как мы и ожидали. Теперь я меняю test_kernel_include.cl на:

int test_func()
{
  return 2;
}

но результатом по-прежнему является массив, все элементы которого равны 1, который должен измениться на 2, но это не так.


person mmostajab    schedule 10.07.2015    source источник


Ответы (2)


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

К сожалению, эти хэши не содержат никаких заголовочных файлов, которые включены в основной исходный код ядра. Это означает, что когда вы меняете что-то во включенном заголовочном файле, драйвер, по существу, игнорирует это изменение и перезагружает предыдущий бинарный файл ядра с диска (если только что-то не изменилось и в основном исходном коде ядра).

В системах Linux кеш ядра можно найти в ~/.nv/ComputeCache. Если вы удалите этот каталог после внесения изменений в один из ваших включаемых файлов, это должно заставить драйвер фактически перекомпилировать ядро ​​​​OpenCL.

person jprice    schedule 10.07.2015
comment
Также в окнах можно найти %AppData%\NVIDIA\ComputeCache. Эта глупая вещь также применима к AMD и Intel или она специфична для компилятора nvidia? - person mmostajab; 10.07.2015
comment
Я только заметил эту проблему с NVIDIA. Другие также могут реализовывать схемы кэширования, но, возможно, они учитывают включенные заголовки. - person jprice; 10.07.2015
comment
Я просто добавил del /Q /S %APPDATA%\NVIDIA\ComputeCache* в свое событие предварительной сборки в Visual Studio, теперь он всегда удаляет кеш компилятора перед повторным запуском приложения :) - person mmostajab; 10.07.2015
comment
или мы можем добавить system("erase /Q /S %APPDATA%\\NVIDIA\\ComputeCache\\*"); в начало основной функции :) - person mmostajab; 10.07.2015

Сделайте это перед инициализацией платформы:

setenv("CUDA_CACHE_DISABLE", "1", 1);

Это отключит механизм кэширования сборки. Он также работает для платформы OpenCL, хотя и говорит, что CUDA.

person DarkZeros    schedule 10.07.2015
comment
В винде тоже работает? потому что я пробовал, но setenv не был определен. - person mmostajab; 10.07.2015
comment
@mmostajab Эквивалент Windows будет _putenv_s("CUDA_CACHE_DISABLE", "1"); - person jprice; 10.07.2015