【问题标题】:'__kernel' does not name a type'__kernel' 没有命名类型
【发布时间】:2015-06-09 19:01:38
【问题描述】:

我正在尝试编译此处找到的代码:http://developer.amd.com/tools-and-sdks/opencl-zone/opencl-resources/introductory-tutorial-to-opencl/

我正在用命令编译它:

g++ -Wall -O2 -lm -lOpenCL -g -Wno-unknown-pragmas foo.cpp -o foo

导致问题的代码部分是这样的:

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
 __constant char hw[] = "Hello World\n";

 __kernel void hello(__global char * out) {
      size_t tid = get_global_id(0);
      out[tid] = hw[tid];
}

我收到以下错误:

foo.cpp:105:2: error: ‘__constant’ does not name a type
  __constant char hw[] = "Hello World\n";

foo.cpp:107:2: error: ‘__kernel’ does not name a type
  __kernel void hello(__global char * out) {

有人可以解释为什么会这样吗?标题与链接上的完全相同。

谢谢

【问题讨论】:

  • 看起来您正在尝试将 OpenCL 代码编译为本机代码(以在您的 CPU 上运行)。据我所知,gcc 不承认 opencl 是一种语言。您需要一个 opencl 编译器来编译代码。 Clang 确实理解 opencl,但如果没有运行时库形式的进一步支持,您仍然无法将其编译为本机应用程序。使用 OpenCL 的正常方法是使用 clCreateProgramFromSource()、clBuildProgram()、clCreateKernel() 和 clEnqueueNDRange() [之前/之后有一些样板]
  • @MatsPetersson 是正确的(应该将其作为答案提交)
  • 我没有按照链接的建议尝试使用 GCC 进行编译。我正在使用带有 -lOpenCl 的 g++,他应该工作这就是为什么我很困惑......其他 opencl 函数调用都发现它只是内核方法的声明是一个问题
  • g++ 是 gcc C++ 变体。正如我在下面的回答中所描述的,内核是使用 clCreateProgramWithSource 或类似的东西从您的 OpenCL 主机代码编译而来的。 AMD 工具很可能还有一个离线编译器,您可以使用它来创建二进制文件,然后可以使用 clCreateProgramWithBinary 加载该文件,但我很确定这对您没有多大帮助。我在 ARM 使用 OpenCL,所以不知道 AMD 解决方案的细节,但我希望它与 ARM 产品有很多相似之处。

标签: c++ parallel-processing kernel opencl


【解决方案1】:

你不能编译这样的 OpenCL 代码(没有更多的支持基础设施,例如支持 OpenCL 的编译器和用于 OpenCL 功能的库 - Clang 能够为 x86 编译 OpenCL,但随后抱怨没有尝试链接事物时的支持库)。

典型的 OpenCL 应用程序如下所示:

// Get platform, device and context - this is about 10-20 lines of "boilerplate" code. 
const char* source = "... your code goes here ...";
// But you could of course read it from a file, for example!
cl_int err;
clProgram prog = clCreateProgramWithSource(context, 1, &source, NULL, &err);
err = clBuildProgram(prog, 1, &device, NULL, NULL, NULL);
cl_kernel kern = clCreateKernel(prog, "hello", &err);
cl_mem out = clCreateBuffer(context, CL_MEM_READ_WRITE, 100, NULL, err);
err = clSetKernelArg(kernel, 0, sizeof(out), out);
size_t range = 1;
cl_command_queue queue = cl_create_command_queue( ... );
cl_event event;
err = clEnqueueNDRange(queue, kern, 1, NULL, &size, NULL, 0, NULL, &event);
clFlush(queue);
clWaitForEvent(event);
// Lots of lines of code to release everything. 

[上面几行我是手写的——我家里没有CL环境,所以不能查——它显示了一般原理,我跳过了相当多的setup/teardown代码- 当然,每次调用 OpenCL 库时都应该进行错误检查,因为通常很容易出错并返回错误,然后导致下一步崩溃/出错]

有一些面向对象的变体,可以让您避免一些清理工作(析构函数会为您完成),但由于我只编写过几次这样的代码 [vs.多次使用上面显示的基本 C 版本],我必须阅读文档或查看我在工作中的“OpenCL C++ 绑定卡”。

【讨论】:

    【解决方案2】:

    我在同一个教程中遇到了同样的问题。这是我克服它的尝试。

    该教程令人困惑的部分是它为您提供了 OpenCL 代码,而没有明确告诉您将该代码放在名为“lesson1_kernel.cl”的文件中

    我发现了这一点,因为在本教程的前面,本机代码会读取此文件:

    std::ifstream file("lesson1_kernels.cl");
    checkErr(file.is_open() ? CL_SUCCESS:-1, "lesson1_kernel.cl");
    std::string prog(
        std::istreambuf_iterator<char>(file),
        (std::istreambuf_iterator<char>()));
    cl::Program::Sources source(
        1,
        std::make_pair(prog.c_str(), prog.length()+1));
    

    该教程中之前的所有“本机代码”都属于您将要编译的文件。根据教程的说明,本机代码属于一个名为“lesson1.cpp”的文件

    gcc –o hello_world –Ipath-OpenCL-include –Lpath-OpenCL-libdir lesson1.cpp –lOpenCL
    

    我不想为这样一个简单的一次性脚本创建一个新的课程 1_kernels.cl 文件,所以我将所有 OpenCL 代码放入一个字符串中,并用它创建了 cl::Program::Sources 对象使用适当的转义字符的字符串:

    const std::string openCLCode("#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable\n__constant char hw[] = \"Hello World\\n\";\n__kernel void hello(__global char * out) \n\n{\n  size_t tid = get_global_id(0);\n  out[tid] = hw[tid];\n}\n");
    

    和:

    cl::Program::Sources source(
        1,
        std::make_pair(openCLCode.c_str(), openCLCode.length()+1));
    cl::Program program(context, source);
    

    一旦我这样做了,我就能够编译和运行该程序,而不会出现其他问题。感谢 theNoobProgrammer 发布我的问题,感谢 Matts Petersson 帮助我解决了这个问题,而无需大量修改教程代码。

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 2023-04-07
      • 2021-02-03
      • 2017-04-01
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多