5

我正在尝试将 OpenCL C++ 包装 API 用于以下程序:

#define __CL_ENABLE_EXCEPTIONS


#include <CL/cl.hpp>
#include <cstdio>
#include <cstdlib>
#include <iostream>

 const char helloStr []  = "__kernel void "
                          "hello(void) "
                          "{ "
                          "  "
                          "} ";

 int
 main(void)
 {
    cl_int err = CL_SUCCESS;
    try {

      std::vector<cl::Platform> platforms;
      cl::Platform::get(&platforms);
      if (platforms.size() == 0) {
          std::cout << "Platform size 0\n";
          return -1;
      }

      cl_context_properties properties[] =
         { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0};
      cl::Context context(CL_DEVICE_TYPE_CPU, properties);

      std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();

      cl::Program::Sources source(1,
          std::make_pair(helloStr,strlen(helloStr)));
      cl::Program program_ = cl::Program(context, source);
      program_.build(devices);

      cl::Kernel kernel(program_, "hello", &err);

      cl::Event event;
      cl::CommandQueue queue(context, devices[0], 0, &err);
      queue.enqueueNDRangeKernel(
          kernel,
          cl::NullRange,
          cl::NDRange(4,4),
          cl::NullRange,
          NULL,
          &event);

      event.wait();
    }
    catch (cl::Error err) {
       std::cerr
          << "ERROR: "
          << err.what()
          << "("
          << err.err()
          << ")"
          << std::endl;
    }

   return EXIT_SUCCESS;
 }

我使用该博客文章中的相同内核文件,无论如何这不是问题,因为我无法通过编译。

我正在使用以下命令编译程序:

g++ example.cpp -o example -l OpenCL

我收到以下错误消息:

/tmp/ccbUf7dB.o: In function `cl::detail::ReferenceHandler<_cl_device_id*>::release(_cl_device_id*)':
example.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP13_cl_device_idE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP13_cl_device_idE7releaseES3_]+0x14): undefined reference to `clReleaseDevice'
collect2: error: ld returned 1 exit status

我已经阅读了有关 clReleaseDevice 不适用于旧设备的内容(例如,请参阅此问题),但我的显卡是最新的(NVidia GTX 660 Ti,支持 OpenCL 1.2)。我可以从那里去哪里?

我在 Ubuntu 13.04 x64 上运行它,并从 ubuntu 存储库安装了 nvidia-opencl-dev 和 opencl-headers。

4

2 回答 2

10

根本原因

问题是您链接的 OpenCL 库不支持 OpenCL 1.2。笼统地说,在支持您要使用的版本的 OpenCL 实现可用于特定平台之前,当链接到随它提供的 OpenCL 共享库时,您将遇到这个问题。有两种解决方案:

  • 从 Khronos 下载与您选择的硬件提供的 OpenCL 版本相匹配的 cl.hpp 版本,并继续使用设备制造商提供的库。
  • 链接到实现最新 OpenCL 标准的 OpenCL 共享库,但编写多个代码路径 - 每个 OpenCL 版本一个,确保每个代码路径仅使用该版本支持的 OpenCL 功能。这条路线更难,我不知道如何使用 C++ 包装器来实现。如果您尝试在不支持 OpenCL 1.2 的平台上调用 OpenCL 1.2 函数,您将收到段错误,这就是需要不同代码路径的原因。

英伟达专用

Nvidia 在提供 OpenCL 1.2 支持方面非常缓慢。结果,他们的 OpenCL 库没有提供链接器正在寻找的 OpenCL 1.2 函数,从而导致错误。

2015 年 5 月,Nvidia 发布了支持 OpenCL 1.2 的驱动程序,请参阅下面 Z Boson 的评论。更新驱动程序应该可以解决链接器错误。GeForce GTX 6xx 和更高版本的显卡(前几代的更名除外)支持 OpenCL 1.2。您可以在 Khronos OpenCL 网站上查看符合标准的产品列表以确保。列出了 GTX 660 Ti,所以你很幸运。

于 2013-04-07T18:32:32.223 回答
0

是的。我从未在 Nvidia 设备上看到过 OpenCL 1.2。在您的系统上编译它,然后查看“OpenCL C 版本”:

#include <iostream>
#include <vector>
#include <CL/cl.hpp>

int main() {

    // Get the platforms
    std::vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    // Loop over the number of platforms
    for ( size_t i = 0; i < platforms.size(); ++i ) {

        // Display the platform information
        std::cout << "Platform " << i+1 << ": "
                            << platforms[i].getInfo<CL_PLATFORM_NAME>()
        << "\n----------------------------------------------"
        << "\nVendor    : " << platforms[i].getInfo<CL_PLATFORM_VENDOR>()
        << "\nVersion   : " << platforms[i].getInfo<CL_PLATFORM_VERSION>();

        // Get the devices on the current platform
        std::vector <cl::Device> devices;
        platforms[i].getDevices( CL_DEVICE_TYPE_ALL , & devices);

        // Loop over the devices
        std::cout << "\n----------------------------------------------\n";
        for ( size_t j = 0; j < devices.size(); ++j ) {

            // Display the device information
            std::cout
            << "\n   Device " << j+1 << ": "
            <<          devices[j].getInfo< CL_DEVICE_NAME >()
            << "\n\t Device Version     : "
            <<          devices[j].getInfo< CL_DEVICE_VERSION >()
            << "\n\t OpenCL C Version   : "
            <<          devices[j].getInfo< CL_DEVICE_OPENCL_C_VERSION >()
            << "\n\t Compute Units      : "
            <<          devices[j].getInfo< CL_DEVICE_MAX_COMPUTE_UNITS >()
            << "\n\t Max Work Group Size: "
            <<          devices[j].getInfo< CL_DEVICE_MAX_WORK_GROUP_SIZE >()
            << "\n\t Clock Frequency    : "
            <<          devices[j].getInfo< CL_DEVICE_MAX_CLOCK_FREQUENCY >()
            << "\n\t Local Memory Size  : "
            <<          devices[j].getInfo< CL_DEVICE_LOCAL_MEM_SIZE >()
            << "\n\t Global Memory Size : "
            <<          devices[j].getInfo< CL_DEVICE_GLOBAL_MEM_SIZE >();

            // Check if the device supports double precision
            std::string str = devices[j].getInfo<CL_DEVICE_EXTENSIONS>();
            size_t found = str.find("cl_khr_fp64");
            std::cout << "\n\t Double Precision   : ";
            if ( found != std::string::npos ){ std::cout << "yes\n"; }
            else {                             std::cout <<  "no\n"; }
        }
        std::cout << "\n----------------------------------------------\n";
    }
//  std::cin.ignore();
    return 0;
}
于 2014-08-08T09:26:38.260 回答