【问题标题】:Using clang to compile .cl kernel file使用 clang 编译 .cl 内核文件
【发布时间】:2021-07-26 08:27:34
【问题描述】:

我的环境:

Ubuntu clang version 12.0.0-3ubuntu1~20.04.3
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

我的问题: 当我这样做时:

$ clang -cl-std=CLC++ ./test.cl

./test.cl 文件在哪:

template<class T>
T add( T x, T y )
{
    return x + y;
}
kernel void k(){}

一个错误提示:

/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crt1.o: in function _start': (.text+0x24): undefined reference to main'

我想知道如何解决这个问题?我什至无法编译支持 C++ 功能的最简单的 .cl 文件。谢谢大家!

【问题讨论】:

  • 如果您只想编译代码,请使用-c 选项
  • 感谢您的耐心等待!添加-c命令后我成功,现在我得到.o文件,我可以使用这个文件通过clCreateProgramWithBinary()创建一个Opencl程序吗?

标签: c++ clang opencl


【解决方案1】:

您不会使用 clang 编译 .cl 文件。您编译 .c/.cpp C/C++ 源文件。在 C/C++ 代码中,将 .cl 文件作为字符串 (kernel_code) 加载,并将其与 device 一起传递给 OpenCL C/C++ bindings。然后,可执行文件将在运行时从 kernel_code 字符串编译 OpenCL C 代码,并将供应商特定的程序集传递到设备 (GPU)。

这是在运行时执行 CpenCL C 计算的 C++ 代码:

//const cl::Device device = ...;
//const string kernel_code = ...;

cl::Context context = cl::Context(device);
cl::CommandQueue queue = cl::CommandQueue(context, device); // queue to push commands for the device
cl::Program::Sources source;
source.push_back({ kernel_code.c_str(), kernel_code.length() });
cl::Program program = cl::Program(context, source);
int error = program.build("-cl-fast-relaxed-math"); // compile OpenCL C code
if(error) cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device) << endl; // print build log if errors occur during OpenCL C compiling

然后您创建cl::Buffer 对象(分配设备内存),在 OpenCL C 代码中创建与内核对应的 cl::Kernel 对象,使用 kernel.setArg(...); 以正确的顺序将缓冲区链接到内核并在queuequeue.enqueueNDRangeKernel(...);queue.finish();

【讨论】:

  • 感谢您的耐心等待!你描述的方式是在线编译,但是我想离线编译(转成二进制,所以我可以使用clCreateProgramWithBinary()),所以我跟着Clang user manual做了这个,但是我失败了。
  • 嗯...不,您完全可以使用 Clang 编译 .cl。大多数 OpenCL 实现都是这样做的,他们在引擎盖下有 Clang。这里的问题是如何生成您的特定 OpenCL 驱动程序可以理解的目标文件。如果它支持 SPIR 或 SPIR-V - 很好,你不需要其他任何东西。否则,事情会很有趣。
【解决方案2】:

这取决于您的目标平台。例如,您可以使用 clang 离线编译 AMD GCN 架构的 OpenCL 二进制内核(如果您使用的是 ROCm 驱动程序)。您可以使用一些显式或隐式支持 SPIR(在 SPIR-V 之前)的旧 OpenCL 实现,因为它基于 LLVM IR。对于支持 SPIR-V 的 OpenCL 平台,您可以使用 SPIR-V 转换器添加额外的步骤(例如,https://github.com/KhronosGroup/SPIRV-LLVM-Translator)。

【讨论】:

  • 非常感谢,看来clang只是整个编译过程的一个步骤,我也在OpenCL github上发了这个问题,有人告诉我检查这个page,我我试图通过这个。希望这会奏效:)
  • @Glinttsd 是的,这是正确的过程,以防您的目标实现支持 SPIR-V,并且大多数最新版本都应该支持。当不支持 SPIR-V 时,乐趣就开始了……
  • 我目前的实现是NVIDIA GeForce GTX 1050 Ti,我认为它支持:)我没有机会享受“乐趣”哈哈
  • @Glinttsd 你很幸运,你可以同时使用 SPIR-V 和 PTX 后端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
  • 2020-09-24
  • 2015-02-15
  • 2012-10-15
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多