include headers to OpenCL .cl file

2019-03-27 06:47发布

I've written an OpenCL kernel in a .cl file. It attempts to #include several headers.

Its compilation fails, since the included header files are "not found". I am aware that clBuildProgram can take the -I dir option, which adds the directory dir to the list of directories to be searched for the header files.

In the khronus site forum this post http://www.khronos.org/message_boards/viewtopic.php?f=37&t=2535 talks about the issue.

They propose to use clCreateProgramWithSource which specifies all sources (including .h files).

I have a questions regarding this issue:

  1. Which option is better? (clBuildProgram vs. clCreateProgramWithSource, as described above)
  2. If I use clCreateProgramWithSource how does the compiler know what to include? I mean, which source stands for which included file name?
  3. If I use clBuildProgram and there are several directories with include files, how do I specify them?

3条回答
走好不送
2楼-- · 2019-03-27 07:05

There is one more dirty trick: you should emulate include yourself (i. e. something like manual amalgamation). It is not very clear for coding, but it works if your OpenCL compiler doesn't support (or supports incorrectly) -I directives. This approach is not perfect (for example, you lose syntax highlighting), but can help for old or buggy OpenCL compilers.

Small simple example of this possibility:

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)
查看更多
相关推荐>>
3楼-- · 2019-03-27 07:06

The Nvidia OpenCL device drivers have a bug when using -I with a certain number of includes and code length. AMD and Intel don't have this problem. My solutions is to instead concatenate all the .cl files into one large one at runtime. The disadvantage of this is that in debugging code the line number of the error corresponds to the concatentated .cl file and not in the individual .cl files.

I doubt Nvidia will ever fix this. They don't care about OpenCL much anymore.

查看更多
虎瘦雄心在
4楼-- · 2019-03-27 07:17

OpenCL requires you use clCreateProgramWithSource() followed by clBuildProgram().

ClCreateProgramWithSource() creates and returns a cl_program object.

That cl_program object is input into clBuildProgram().

clBuildProgram() allows you to specify compiler options which include the include file directories. In your case, for header file includes, it will be something like the string:

-I myincludedir1 -I myincludedir2  ...

The compiler used is the internal OpenCL compiler in the OpenCL SDK you are using. So if you are using AMD's SDK, the AMD OpenCL compiler that is part of their OpenCL SDK will be used. Likewise for Nvidia or Intel.

Its important to check the OpenCL status code for ALL OpenCL function calls. This is mandatory for clCreateProgramWithSource() and clBuildProrgam() to get any compiler errors or messages. There is a whole other bit code to write to get the size of the messages and then retrieve the messages themselves.

查看更多
登录 后发表回答