Большая часть проблем - это установка необходимых библиотек для поддержки opencl, даже на linux у меня были конфликты (решаемые) когда на машину одновременно устанавливались intel opencl, nvidia driver проприетарный и amd rocm
начни от
сюда
Удостоверься что у тебя все установлено под твою видеокарту (не помогу с windows, там с интервалом раз в 3-4 года много что меняется именно в среде gpu-computing, не мудрено что все готовые сборки нейронных сетей типа SD или GPT для pytorch таскают с собой гигабайты готовых предустановленных окружений.
----------
Про c++ враппер, год назад я пробовал устанавливать и использовать различные врапперы (я так понял они все на одном и том же основаны, так как вот такой изврат ...
getInfo<CL_DEVICE_NAME>()
сложно не заметить) и спотыкался на банальном запуске примеров из документации.
Плюнул, и разобрался с
https://man.opencl.org/ нагуглив любой минимальный пример, хоть
этот древний
Так вот главная рекомендация банальна и тупа - проверяй сообщение об ошибке каждого метода, сэкономишь тьму времени на отладке (а отладка cl грустная, так как все значения скрыты, структуры косвенные)
Я написал себе макрос и хелпер/* макрос, помогающий обрабатывать ошибки opencl методов и автоматическое завершение работы при любой ошибке, с корректным освобождением ресурсов
Использовать так CL_RET = clMethod....
при возникновении ошибки сгенерирует исключение, в котором будет содержаться текущие имя файла и строка
*/
/* если нужно в сообщении об ошибке сообщать имя файла исходников и номер строки */
/**/#define CL_RET main_cl.error(__FILE__,__LINE__)
/* если нужно в сообщении об ошибке сообщать имя файла исходников и номер строки но проигнорировать один код ошибки */
/**/#define CL_RET_IGNORE(id) main_cl.error(__FILE__,__LINE__,id)
/* код ошибки не будет содержать имени файла и строки */
//**/#define CL_RET main_cl
/* класс-обертка над стандартными операциями по инициализации OpenCL, обработка ошибок и т.п. */
class CLHelper
{
public:
/* хранится последнее значение кода ошибки метода, перед которым поставили макрос CL_RET */
cl_int ret;
/* последнее значение имни файла исходников места последнего вызова макроса CL_RET */
char* file=NULL;
/* последнее значение строчки файла исходников места последнего вызова макроса CL_RET */
int line;
cl_int ignore_ret;
/* код фиксации текущего имени файла и строки, вызывается в макросе CL_RET */
inline CLHelper& error(const char* _file,const int _line,cl_int _ignore_ret=-999999)
{
file=const_cast<char*>(_file);
line=_line;
ignore_ret=_ignore_ret;
return *this;
}
/* подмена оператора = для красивого использования CL_RET */
inline void operator=(cl_int _ret)
{
ret=_ret;
if(ret==CL_SUCCESS||(ignore_ret!=-999999&&ret==ignore_ret)) return;
//std::string msg=std::to_string("OpenCL error in ")+std::string(file)+":"+std::to_string(line);
std::string msg="OpenCL error ";
if(file!=NULL)
{
msg+="in ";
msg+=file;
msg+=":"+std::to_string(line)+" ret=";
}
msg+=ret_str(ret);
throw std::runtime_error(msg);
}
...
}
трансляция кода ошибки в строку
кусок кода вывода подробного сообщения об ошибке компиляции .cl файла с kernel
CL_RET_IGNORE(CL_BUILD_PROGRAM_FAILURE) = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
if(main_cl.ret==CL_BUILD_PROGRAM_FAILURE)
{
size_t build_log_len;
CL_RET = clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &build_log_len);
char buff_erro[build_log_len];
CL_RET = clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, build_log_len, buff_erro, NULL);
std::cerr << buff_erro;
CL_RET = CL_BUILD_PROGRAM_FAILURE; // компиляция завершена с ошибкой но чтобы вывести лог компиляции выход отложили
}
Использовать так
CL_RET = clGetPlatformIDs(MAX_PLATFORMS, platforms_id, &ret_num_platform);
или так
program = clCreateProgramWithSource(context, 1, (const char **)&cstr, (const size_t *)&source_size, &ret);
CL_RET=ret;
будет вызвано исключение с подробным сообщением об ошибке и его месте в коде
соединять c-style код с c++ std не сложно, в случае с opencl тебе и так придется так или иначе выходить за рамки абстракций и опускаться до работы с буферами памяти... так зачем лишние прослойки