如何编译OpenCL程序以使用自行编译的ICD-Loader而非系统版本
你的核心问题在于Windows的DLL加载优先级规则:系统目录(C:\Windows\System32)的优先级远高于自定义路径,所以哪怕你编译时链接了自己的OpenCL.lib,运行时系统还是会优先加载system32里的Nvidia版OpenCL.dll。下面是几个无需管理员权限就能解决的方案,按优先级从高到低推荐:
1. 将自定义ICD-Loader与程序可执行文件放在同一目录
这是最简单可靠的方法,因为Windows加载DLL时,会首先检查当前进程的工作目录(也就是exe所在的文件夹)。
针对CMake项目的自动配置
可以在CMakeLists.txt里添加一个POST_BUILD命令,编译完成后自动把你的补丁版OpenCL.dll复制到exe输出目录:
cmake_minimum_required(VERSION 3.7) project(listDevices C) set(OpenCL_LIBRARY "C:/GitHub/OpenCL-ICD-Loader/install/lib/OpenCL.lib") set(OpenCL_INCLUDE_DIR "C:/GitHub/OpenCL-Headers/install/include") find_package( OpenCL REQUIRED ) file(GLOB libsrc src/*.c) file(GLOB libhdr include/*.h*) set(srcFiles ${libhdr} ${libsrc}) include_directories( ${OPENCL_INCLUDE_DIR} ) add_executable( ${PROJECT_NAME} ${srcFiles} ) target_link_libraries( ${PROJECT_NAME} OpenCL::OpenCL ) # 添加自动复制DLL的步骤 add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "C:/GitHub/OpenCL-ICD-Loader/install/bin/OpenCL.dll" $<TARGET_FILE_DIR:${PROJECT_NAME}> )
这样每次编译后,你的自定义OpenCL.dll会自动出现在exe旁边,运行时就会优先加载它。
针对手动clang编译的情况
编译完成后,直接把C:/GitHub/OpenCL-ICD-Loader/install/bin/OpenCL.dll复制到生成的listDevices.exe所在的文件夹,双击运行exe即可加载自定义Loader。
2. 临时修改PATH环境变量(适合调试场景)
如果你不想每次复制DLL,可以在运行程序前,把自定义ICD-Loader的bin目录添加到PATH的最前面:
set PATH=C:\GitHub\OpenCL-ICD-Loader\install\bin;%PATH% listDevices.exe
Windows会优先从PATH靠前的目录查找DLL,这样就能加载你的自定义版本。注意这个修改是临时的,只对当前命令行窗口有效,无需管理员权限。
3. 确认自定义ICD-Loader的补丁生效
你提到已经修改了ICD-Loader代码让它读取HKEY_CURRENT_USER的注册表项,需要确保Intel OpenCL CPU Runtime的ICD信息已经正确写入到HKCU\SOFTWARE\Khronos\OpenCL\Vendors下:
- 打开注册表编辑器(
regedit.exe),导航到HKEY_CURRENT_USER\SOFTWARE\Khronos\OpenCL\Vendors - 添加一个字符串值,名称为Intel CPU Runtime的ICD DLL路径(比如
C:\path\to\intel_opencl_icd.dll),值留空即可
这样你的补丁版Loader就能从当前用户注册表找到Intel的ICD,而不需要修改系统级的HKLM项(无需管理员权限)。
为什么之前的方法无效?
你编译时链接的OpenCL.lib只是导入库,它只告诉编译器程序需要调用OpenCL.dll里的函数,但运行时Windows会按照自己的DLL搜索规则去找真正的DLL文件。系统目录的优先级最高,所以即使你链接了自定义lib,还是会加载系统的DLL。
内容的提问来源于stack exchange,提问作者mikulcak

