c++ - 使用 Address Sanitizer 编译主机应用程序时可使用 OpenCL
问题描述
我正在调试我的 OpenCL 应用程序的崩溃。我试图使用 to asan 来确定问题的根源。但是后来我发现打开asan并重新编译后,我的应用程序找不到任何OpenCL设备。简单地添加-fsanitize=address
到编译器选项使我的程序无法使用 OpenCL。
通过进一步的测试,我发现内存清理器不适用于 OpenCL。
为什么会这样?如何将 asan 与 OpenCL 一起使用?
编辑:一个最小的例子
#include <CL/cl.hpp>
#include <vector>
#include <iostream>
int main() {
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if(platforms.size() == 0) std::cerr << "in asas\n";
else std::cout << "compiled normally\n";
}
编辑2:
cl::Platform::get
正常返回 CL_SUCCESS。在获取平台的过程中没有错误。
还有一些关于我的设置的信息。
GPU:GTX 780Ti
驱动程序:418.56
OpenCL SDK:Nvidia OpenCL / POCL 1.3,带有 CPU 和 CUDA 后端
编译器:GCC 8.2.1
操作系统:Arch Linux (Kernel 5.0.7 x64)
解决方案
已知 NVIDIA 驱动程序与 ASAN 冲突。它尝试将内存 mmap(2) 到进程内的固定虚拟内存范围,这与 ASAN 的写保护影子间隙区域一致。鉴于 ASAN 在启动时保留了大约 20TB 的虚拟地址空间,因此与其他程序或驱动程序发生此类冲突的可能性也不大。
ASAN 识别可能在ASAN_OPTIONS
环境变量中设置的某些标志。要解决阴影间隙范围冲突,请将protect_shadow_gap
选项设置为0
。例如,假设一个类似 POSIX 的 shell,你可以像这样运行你的程序
$ ASAN_OPTIONS=protect_shadow_gap=0 ./mandelbrot
在 ASAN 下,可写影子间隙会产生额外的性能成本,因为不受保护的间隙需要自己的影子。这就是为什么不建议全局设置此选项的原因(例如,在您的 shell 启动脚本中)。仅对实际上需要它的程序启用它。
我几乎可以肯定这是您问题的根本原因。我将 ASAN 与 CUDA 程序一起使用,并且始终需要设置此选项。没有它的CUDA报告的失败非常相似:cudaErrorNoDevice
我尝试选择设备时出错。
推荐阅读
- javascript - 时间条件不自行执行,需要重新加载整个页面
- mysql - 使用生成的列创建表
- cron - 使用 SLURM 调度程序的条件 cron 作业
- python-3.x - 如何在python中运行的另一个程序上模拟python中的按键事件
- c# - 用指数计算生成的数学表达式,即 (1+2-3)*4^5 = answer
- javascript - 如何稍后在测试用例中保存和重用动态 DOM 内容
- bash - .sh 文件中的“output_dir="${1%/}" 是什么意思?
- bash - 通过将模式替换为另一个模式来递归地重命名存储库和文件名
- c# - 使用 AspNetCore.OData 进行分页 - 响应中缺少 @odata 属性
- windows - 与实际图像相比,JavaFX DragView Image 降低了不透明度......可以改变吗?