OpenCL not finding platforms?

自作多情 提交于 2019-12-05 16:42:18

My sincerest thanks to @pasternak for helping me troubleshoot this problem. To solve it however I ended up needing to avoid essentially all ubuntu apt-get calls for install and just use the cuda run file for the full installation. Here is what fixed the problem.

  1. Purge existing nvidia and cuda implementations (sudo apt-get purge cuda* nvidia-*)
  2. Download cuda-6.5 toolkit from the CUDA toolkit archive
  3. Reboot computer
  4. Switch to ttyl (Ctrl-Alt-F1)
  5. Stop the X server (sudo stop lightdm)
  6. Run the cuda run file (sh cuda_6.5.14_linux_64.run)
  7. Select 'yes' and accept all defaults
  8. Required reboot
  9. Switch to ttyl, stop X server and run the cuda run file again and select 'yes' and default for everything (including the driver again)
  10. Update PATH to include /usr/local/cuda-6.5/bin and LD_LIBRARY_PATH to include /usr/local/cuda-6.5/lib64
  11. Reboot again
  12. Compile main.c program (gcc main.c -o vectorAddition -l OpenCL -I/usr/local/cuda-6.5/include)
  13. Verify works with ./vectorAddition

C++ API

  1. Download cl.hpp file from Khronos here noting that it is version 1.1
  2. Place cl.hpp file in /usr/local/cuda-6.5/include/CL with other cl headers.
  3. Compile main.cpp (g++ main.cpp -o vectorAddition_cpp -std=c++11 -l OpenCL -I/usr/local/cuda-6.5/include)
  4. Verify it works (./vectorAddition_cpp)

All output from both programs show the correct output for addition between vectors.

I personally find it interesting the Ubuntu's nvidia drivers don't seem to play well with the cuda toolkits. Possibly just for the older versions but still very unexpected.

pasternak

It is hard to say without running the specific code on your machine but looking at the difference between the example C code you said was working and the cl.hpp might give us a clue. In particular, notice that the C example uses the following line to simply read a single platform ID:

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

Notice that is passes 1 as its first argument. This assumes that at least one OpenCL platform exists and requests that the first one found is placed in platform_id. Additionally, note that even though the return code is assigned to "ret" is it not used to actually check if an error is returned.

Now if we look at the implementation of the static method used to queue the set of platforms in cl.hpp, i.e. 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;
}

we see that it first calls

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

notice that the first parameter is 0, which tells the OpenCL runtime to return the number of platforms in "n". If this is successful it then goes on to request the actual "n" platform IDs.

So the difference here is that the C version is not checking that there is at least one platform and simply assuming that one exists, while the cl.hpp variant is and as such maybe it is this call that is failing.

The most likely reason for all this is that the ICD is not correctly installed. You can see this thread for an example of how to fix this issue:

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

I hope this helps.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!