包括 OpenCL .cl 文件的标头

include headers to OpenCL .cl file

本文关键字:文件 OpenCL cl 包括      更新时间:2023-10-16

我在.cl文件中编写了一个 OpenCL 内核。 它尝试#include多个标头。

它的编译失败,因为"找不到"包含的头文件。我知道clBuildProgram可以采用-I dir选项,该选项将目录dir添加到要搜索头文件的目录列表中。

在khronus网站论坛中,这篇文章 http://www.khronos.org/message_boards/viewtopic.php?f=37&t=2535 讨论了这个问题。

他们建议使用指定所有来源(包括.h文件)的clCreateProgramWithSource

我对这个问题有一个问题:

  1. 哪个选项更好?( clBuildProgramclCreateProgramWithSource,如上所述)
  2. 如果我使用clCreateProgramWithSource编译器如何知道要包含的内容?我的意思是,哪个来源代表哪个包含的文件名?
  3. 如果我使用 clBuildProgram 并且有多个包含文件的目录,如何指定它们?

OpenCL 要求您使用clCreateProgramWithSource()后跟 clBuildProgram()

ClCreateProgramWithSource()创建并返回一个cl_program对象。

cl_program对象被输入到clBuildProgram() 中。

clBuildProgram()允许您指定包含包含文件的编译器选项目录。 在您的情况下,对于头文件包含,它将类似于字符串:

-I myincludedir1 -I myincludedir2  ...

使用的编译器是您正在使用的 OpenCL SDK 中的内部 OpenCL 编译器。所以如果你正在使用AMD的SDK,将使用作为其OpenCL SDK一部分的AMD OpenCL编译器英伟达英特尔也是如此。

检查所有 OpenCL 函数调用的 OpenCL 状态代码非常重要。这对于clCreateProgramWithSource()clBuildProrgam()是强制性的任何编译器错误或消息。 还有一整段其他位代码要写获取消息的大小,然后检索消息本身。

Nvidia OpenCL 设备驱动程序在使用具有一定数量的包含和代码长度的 -I 时存在错误。 AMD和英特尔没有这个问题。 我的解决方案是在运行时将所有 .cl 文件连接成一个大文件。 这样做的缺点是,在调试代码中,错误的行号对应于已处理的 .cl 文件,而不是单个 .cl 文件。

我怀疑英伟达永远不会解决这个问题。 他们不再关心OpenCL。

还有一个

肮脏的技巧:你应该模仿包括你自己(即手动合并之类的东西)。编码不是很清楚,但如果 OpenCL 编译器不支持(或错误地支持)-I指令,它可以工作。这种方法并不完美(例如,您丢失了语法突出显示),但可以帮助旧的或有缺陷的 OpenCL 编译器。

这种可能性的小例子:

std::string load_file(const std::string &file_name, int max_size = 0x100000)
{
    FILE *fp = fopen(file_name.c_str(), "rb");
    if (!fp)
    {
        // print some error or throw exception here
        return std::string();
    }
    char *source = new char[max_size];
    size_t source_size = fread(source, 1, max_size, fp);
    fclose(fp);
    if (!source_size)
    {
        delete[] source;
        // print some error or throw exception here
        return std::string();
    }
    std::string result(source);
    delete[] source;
    return result;
}
// errors checks are omitted for simplification
std::string full_source = load_file("header.h");
full_source += load_file("source.cl");
const char *source_ptr = full_source.c_str();
size_t source_size = full_source.size();
cl_int_status = CL_SUCCESS;
cl_program program  = clCreateProgramWithSource(context, 1,
        (const char **)&source_ptr, (const size_t *)&source_size, &ret);
// check status for CL_SUCCESS here
// now you have your program (include + source)