【发布时间】:2011-09-24 00:51:30
【问题描述】:
注意:这个问题与 OpenCL 本身无关...检查最后一段以获得我的问题的简洁陈述。但提供一些背景:
我正在编写一些使用 OpenCL 的 C++ 代码。我喜欢将我的 OpenCL 内核的源代码保存在它们自己的文件中,以简化编码和维护(而不是将源代码直接作为字符串常量嵌入到相关的 C++ 代码中)。这不可避免地会导致在分发二进制文件时如何将它们加载到 OpenCL 运行时的问题——理想情况下,OpenCL 源代码包含在二进制文件中,因此二进制文件不需要位于特定位置在某个目录结构中知道 OpenCL 源代码在哪里。
我想将 OpenCL 文件作为字符串常量包含在某处,最好不使用额外的构建步骤或外部工具(为了跨编译器/跨平台的易用性......即,不接受 @987654323 @ 之类的)。我以为我偶然发现了一种基于 this 线程中第二个答案的技术,如下所示:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
请注意,如果可能的话,我不希望在我的 OpenCL 代码中嵌入 STRINGIFY 宏(正如上面提到的 SO 问题中所做的那样)。现在,这在 Clang/LLVM 编译器上运行得非常好,但是 GCC 死得很惨(“未终止的参数列表调用宏 STRINGIFY”和与 .cl 文件内容相关的各种语法“错误”出现)。所以,很明显,这种精确的技术不能跨编译器使用(没有尝试过 MSVC,但我希望它也能在那里工作)......我怎样才能最小化地按摩它以便它可以跨编译器工作?
总之,我想要一种符合标准的技术,可以将文件内容作为 C/C++ 字符串常量包含在内,而无需调用外部工具或使用无关代码污染文件。想法?
编辑:正如 Potatoswatter 指出的那样,上述行为是未定义的,因此不涉及接触要字符串化的文件的真正交叉编译器预处理器技术可能不是t 可能(第一个发现确实对大多数/所有编译器都有效的令人发指的 hack 的人得到了答案)。出于好奇,我最终执行了第二个回复 here 中的建议...也就是说,我将 STRINGIFY 宏直接添加到了我包含的 OpenCL 文件中:
在somefile.cl:
STRINGIFY(
... // Lots of OpenCL code
)
在somefile.cpp:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
这适用于我尝试过的编译器(Clang 和 GCC,因为它在宏中没有预处理器指令),并且至少在我的上下文中不是太大的负担(即,它不会干扰语法高亮/编辑 OpenCL 文件)。像这样的预处理器方法的一个特点是,由于相邻的字符串被连接起来,你可以写
inline const char* Kernels() {
static const char* kernels =
#include "utility_functions.cl"
#include "somefile.cl"
;
return kernels;
}
只要 STRINGIFY 宏在两个 .cl 文件中,字符串就会连接起来,让您可以模块化您的 OpenCL 代码。
【问题讨论】:
-
对于连接CL代码,clCreateProgramWithSource接受一个字符串列表。
-
啊是的...忘记了。虽然我认为上述方法总体上仍然更容易,因为编译 cl 文件的代码非常简单。
-
为什么不把#include 作为源代码? OpenCL 也会对代码进行预处理,您可以通过
-I编译器选项指定包含文件夹。使文件加载非常舒适......只需让运行时为您完成!不确定它是否可以处理二进制文件,但我想它会工作相同。
标签: c++ include opencl c-preprocessor stringification