这个问题与LLVM / clang有关。
我已经知道如何使用OpenCL API编译opencl-kernel-file(.cl)(clBuildProgram()和clGetProgramBuildInfo())
我的问题是:
如何使用OpenCL 1.2或更高版本将opencl-kernel-file(.cl)编译为LLVM IR?
换句话说,如何在不使用libclc的情况下将opnecl-kernel-file(.cl)编译为LLVM IR?
我尝试了各种方法来获取OpenCL-Kernel-File的LLVM-IR。
我首先遵循了clang用户手册。(https://clang.llvm.org/docs/UsersManual.html#opencl-features)但它没有运行。
其次,我找到了一种使用libclc的方法 命令是这样的:
clang++ -emit-llvm -c -target -nvptx64-nvidial-nvcl -Dcl_clang_storage_class_specifiers -include /usr/local/include/clc/clc.h -fpack-struct=64 -o "$@".bc "$@" <br>
llvm-link "$@".bc /usr/local/lib/clc/nvptx64--nvidiacl.bc -o "$@".linked.bc <br>
llc -mcpu=sm_52 -march=nvptx64 "$@".linked.bc -o "$@".nvptx.s<br>
这种方法工作正常,但由于libclc是在OpenCL 1.1规范之上构建的,因此无法与OpenCL 1.2或更高版本的代码(如使用printf的代码)一起使用。
此方法使用libclc,它以新函数的形式实现OpenCL内置函数。您可以在结果opencl二进制文件的程序集(ptx)中观察到它直接进入函数调用而不是将其转换为内联汇编。我担心这会影响gpu行为和性能,例如执行时间。
所以现在我正在寻找一种使用libclc替换编译的方法
作为最后的手段,我考虑将libclc用于NVPTX后端和LLGP的AMDGPU后端。
但如果还有另一种方式,我想用它
(我希望OpenCL前端我还没有发现铿锵声)
我的计划方案是:
现在,当我将内核源文件编译为LLVM IR时,我必须包含libclc的头文件(上面命令的第一个中的-include选项)来编译内置函数。我必须在编译IR之前链接libclc库到二进制
我的环境如下:
感谢您的建议!
答案 0 :(得分:0)
(我希望我还没有发现OpenCL前端存在于clang中)
在clang中有一个OpenCL前端 - 你正在使用它,否则你无法用clang编译一行OpenCL。前端是Clang识别OpenCL语言。 LLVM中没有OpenCL 后端,它不是LLVM的工作;它是各种OpenCL实现的工作,以提供适当的库。 Clang + LLVM只识别语言并将其编译为bitcode&amp;机器二进制文件,这就完成了。
在结果opencl二进制文件的汇编(ptx)中,它直接进入函数调用,而不是将其转换为内联汇编。
如果找到,可以尝试链接到不同的库而不是libclc。也许NVidia的CUDA在某处有一些bitcode库,然后又是许可问题...顺便说一句,你是否100%确定你需要LLVM IR?使用OpenCL运行时或使用SPIR-V获取OpenCL二进制文件可能会让您获得更快的二进制文件和当然不会那么痛苦。即使你设法得到一个不错的LLVM IR,你也需要一些实际接受它的运行时(我可能是错的,但我怀疑专有的AMD / NVIDIA OpenCL只会接受随机LLVM IR作为输入)。
答案 1 :(得分:0)
Clang没有提供标准的CL声明头文件(例如,C的stdio.h),这就是为什么你得到“未定义的类型浮点数”等等。
如果你得到一个这样的标题,你可以使用“clang -include cl.h -x cl [你的文件名在这里]”将其标记为隐式包含
可以从
的参考OpenCL编译器实现中检索一个这样的声明头https://github.com/KhronosGroup/SPIR-Tools/blob/master/headers/opencl_spir.h
顺便说一下,考虑使用这个生成SPIR(尽管是1.0)的编译器,它可以作为输入提供给OpenCL驱动程序。
答案 2 :(得分:0)
Clang 9(及更高版本)可以编译用OpenCL C语言编写的OpenCL内核。您可以通过传递-emit-llvm
标志(添加-S
来告诉Clang发出LLVM-IR,以文本而不是字节码格式输出IR),然后使用以下命令指定OpenCL标准的版本: -cl-std=CL2.0
。 Clang当前最多支持OpenCL 2.0。
默认情况下,Clang不会添加标准的OpenCL标头,因此,如果您的内核使用任何OpenCL内置函数,您可能会看到类似以下的错误:
clang-9 -c -x cl -emit-llvm -S -cl-std=CL2.0 my_kernel.cl -o my_kernel.ll
my_kernel.cl:17:12: error: implicit declaration of function 'get_global_id' is invalid in OpenCL
int i = get_global_id(0);
^
1 error generated.
您可以通过将-finclude-default-header
标志传递给Clang前端来告诉Clang包含standard OpenCL headers,例如
clang-9 -c -x cl -emit-llvm -S -cl-std=CL2.0 -Xclang -finclude-default-header my_kernel.cl -o my_kernel.ll