OpenCL没有找到平台?

时间:2015-03-20 16:35:35

标签: c++ opencl gpu

我正在尝试使用OpenCL的C ++ API。我已经安装了我的NVIDIA驱动程序,并且测试过我可以运行here提供的简单向量添加程序。我可以使用以下gcc调用编译该程序,程序运行没有问题。

gcc main.c -o vectorAddition -l OpenCL -I/usr/local/cuda-6.5/include

但是,我更倾向于使用C ++ API而不是C所需的非常详细的主机文件。

我从here下载了来自Khronos的C ++绑定,并将cl.hpp文件放在与我的其他cl.h文件相同的位置。代码使用了一些C ++ 11,因此我可以用以下代码编译代码:

g++ main.cpp -o vectorAddition_cpp -std=c++11 -l OpenCL -I/usr/local/cuda-6.5/include

但是当我尝试运行该程序时,我收到错误:

clGetPlatformIDs(-1001)

我还尝试了提供here的示例,它提供了更有用的错误消息。

No platforms found. Check OpenCL installation!

提供此错误的特定代码是:

std::vector<cl::Platform> all_platforms;
    cl::Platform::get(&all_platforms);
    if(all_platforms.size()==0){
    std::cout<<" No platforms found. Check OpenCL installation!\n";
    exit(1);
    }

这看起来很奇怪,因为C实现运行没有问题。任何见解都将深表感谢。

修改

C实现实际上没有正确运行。每次添加都打印为等于零。检查ret_num_platforms也会返回0.由于某种原因,我的设置无法找到我的GPU。我能错过什么?我的安装包括分别通过apt-get.run文件安装的nvidia-340驱动程序和cuda-6.5。

2 个答案:

答案 0 :(得分:4)

我最诚挚的感谢@pasternak帮助我解决了这个问题。为了解决它,我最终需要避免基本上所有ubuntu apt-get调用安装,只需使用cuda运行文件进行完整安装。以下是解决问题的方法。

  1. 清除现有的nvidia和cuda实施(sudo apt-get purge cuda* nvidia-*
  2. CUDA toolkit archive
  3. 下载cuda-6.5工具包
  4. 重新启动计算机
  5. 切换到ttyl(Ctrl-Alt-F1)
  6. 停止X服务器(sudo stop lightdm)
  7. 运行cuda运行文件(sh cuda_6.5.14_linux_64.run
  8. 选择“是”&#39;并接受所有默认值
  9. 必须重启
  10. 切换到ttyl,停止X服务器并再次运行cuda运行文件并选择“是”&#39;一切都是默认的(包括驱动程序)
  11. 更新PATH以包含/usr/local/cuda-6.5/binLD_LIBRARY_PATH 包括/usr/local/cuda-6.5/lib64
  12. 重新启动
  13. 编译main.c程序(gcc main.c -o vectorAddition -l OpenCL -I/usr/local/cuda-6.5/include
  14. 验证是否适用于./vectorAddition
  15. C ++ API

    1. 从Khronos here下载cl.hpp文件,注意它是版本1.1
    2. 将cl.hpp文件放在/usr/local/cuda-6.5/include/CL和其他cl标题中。
    3. 编译main.cpp(g++ main.cpp -o vectorAddition_cpp -std=c++11 -l OpenCL -I/usr/local/cuda-6.5/include
    4. 验证它有效(./vectorAddition_cpp
    5. 两个程序的所有输出都显示了矢量之间相加的正确输出。

      我个人觉得有趣的是,Ubuntu的nvidia驱动程序似乎与cuda工具包不太匹配。可能仅适用于旧版本,但仍然非常出乎意料。

答案 1 :(得分:2)

很难说没有在你的机器上运行特定的代码,但是看看你说的工作的示例C代码和cl.hpp之间的区别可能会给我们一个线索。特别要注意的是,C示例使用以下行来简单地读取单个平台ID:

cl_platform_id platform_id = NULL; 
cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);

请注意,它是第一个参数传递1。这假设至少存在一个OpenCL平台,并请求找到的第一个OpenCL平台放在platform_id中。另外,请注意,即使将返回代码分配给“ret”,也不会用于实际检查是否返回错误。

现在,如果我们看一下用于对cl.hpp中的平台集进行排队的静态方法的实现,即cl :: Platform :: get:

static cl_int get(
    VECTOR_CLASS<Platform>* platforms)
{
    cl_uint n = 0;
    cl_int err = ::clGetPlatformIDs(0, NULL, &n);
    if (err != CL_SUCCESS) {
        return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
    }

    cl_platform_id* ids = (cl_platform_id*) alloca(
        n * sizeof(cl_platform_id));
    err = ::clGetPlatformIDs(n, ids, NULL);
    if (err != CL_SUCCESS) {
        return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
    }

    platforms->assign(&ids[0], &ids[n]);
    return CL_SUCCESS;
}

我们看到它首先调用

::clGetPlatformIDs(0, NULL, &n);

注意第一个参数是0,它告诉OpenCL运行时返回“n”中的平台数。如果成功,则继续请求实际的“n”平台ID。

所以这里的区别在于C版本没有检查是否存在至少一个平台而只是假设存在一个平台,而cl.hpp变体就是这样,也许这个调用失败了。

所有这一切的最可能原因是未正确安装ICD。您可以查看此主题以获取解决此问题的示例:

ERROR: clGetPlatformIDs -1001 when running OpenCL code (Linux)

我希望这会有所帮助。