viernes, 18 de mayo de 2012

Installing OpenCL in Ubuntu 12.04

OpenCL is the new standard for "heterogeneous computing". This is a fancy way of saying that it enables us to write code that will seamlessly run both in CPU and GPU without any changes, unlike for example CUDA which only runs on GPUs.

Now, my laptop doesn't have any GPU (who has the money for that??), but I want to use OpenCL for some computations. Luckily, Intel provides an implementation of the OpenCL standard which runs on any CPU, not just the Intel ones, without the need of installing additional and proprietary Linux drivers.

The SDK provided by Intel comes in an RPM format so it is not Ubuntu-friendly. Thankfully, it is possible to convert the RPM to a .deb package and, with some additional tweaking, having a working OpenCL installation. Most of the following instructions were extracted from the ~mhr3 blog so credit goes for them.

OK, now, for the actual install:
  1. Download the Intel SDK for OpenCL Applications from Intel's web site (http://software.intel.com/en-us/articles/vcsource-tools-opencl-sdk/). The download options are not easy to spot in the messy page, they are on the top right bo. After downloading, you will end with a .tgz file with an RPM inside (crazy, I know). In my case, the file is named intel_sdk_for_ocl_applications_2012_x64.tgz.
  2. Extract the RPM from the .tgz file:
    $ tar zxvf intel_sdk_for_ocl_applications_2012_x64.tgz

    This will extract the intel_ocl_sdk_2012_x64.rpm file.
  3. Convert the RPM file to .deb format and install:
    $ sudo apt-get install -y rpm alien libnuma1    # In case you don't have these packages
    $ fakeroot alien --to-deb intel_ocl_sdk_2012_x64.rpm
    $ sudo dpkg -i intel-ocl-sdk_2.0-31361_amd64.deb
  4. Now the SDK and libraries will be installed to /usr/lib64, while Ubuntu expects them to be in /usr/lib. No problem, just make a symlink and update the library cache:
    $ sudo ln -s /usr/lib64/libOpenCL.so /usr/lib/libOpenCL.so
    $ sudo ldconfig
That's it! OpenCL should be installed now. Let's try with a test program to see the device capabilities.

 #include <iostream>  
 #include <CL/cl.hpp>  
 #include <boost/foreach.hpp>
  
 int main(int, char**) {  
     std::vector<cl::Platform> platforms;  
     cl::Platform::get(&platforms);  
     BOOST_FOREACH(cl::Platform platform, platforms) {  
         std::cout << "Platform: " << platform.getInfo<CL_PLATFORM_NAME>() << std::endl;  
         std::vector<cl::Device> devices;  
         platform.getDevices(CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_CPU, &devices);  
         BOOST_FOREACH(cl::Device device, devices) {  
             std::cout << "Device: " << device.getInfo<CL_DEVICE_TYPE>();  
             std::cout << " (" << CL_DEVICE_TYPE_GPU << " means GPU, " << CL_DEVICE_TYPE_CPU << " means CPU)" << std::endl;  
         }  
     } 
 }  

Save this snippet into opencl.cpp, compile and run:
$ g++ opencl.cpp -lOpenCL -o opencl && ./opencl
Platform: Intel(R) OpenCL
Device: 2 (4 means GPU, 2 means CPU)
This shows that this particular machine has one OpenCL-capable Intel CPU.

Coming up: Making your life easier and using PyOpenCL for your computations.

20 comentarios:

  1. I was able to compile above code but whenever I run it,it gives me no output.

    ResponderEliminar
  2. So this will enable OpenCL for Intel HD 4000? And will I be able to use it in apps like Darktable?

    ResponderEliminar
  3. Thank you very much.
    After having some trouble with the AMD SDK and drivers, it's great to see opencl working. In my system (fresh installed quantal) I needed to install build-essential (for g++) and libboost-all-dev.

    ResponderEliminar
  4. Pls help.. getting error
    /usr/include/CL/cl.hpp:160:19: fatal error: GL/gl.h: No such file or directory
    compilation terminated.

    ResponderEliminar
  5. Try installing the mesa-common-dev package (sudo apt-get install mesa-common-dev)

    ResponderEliminar
  6. Can u suggest me a ebook or tutorial to learn opencl??

    ResponderEliminar
  7. Arun: There are plenty of resources online to learn OpenCL, I don't have any particular reccomendation, but probably Apple's developer site is the way to go.

    Andrew: It doesn't look like there is, unfortunately Intel only provides the 64 bit SDK.

    ResponderEliminar
  8. opencl.cpp:3:30: fatal error: boost/foreach.hpp: No such file or directory
    compilation terminated.

    I get this error.. Can someone please help me out here?

    ResponderEliminar
  9. Surya: The code I posted is just an example, you don't need that header to run OpenCL. If you want to run the code as is, you need to install the Boost development libraries:

    sudo apt-get install libboost-dev

    ResponderEliminar
  10. i have installation problem

    dinesh@dinesh:~/intel_sdk_for_ocl_applications_2013_xe_sdk_3.0.67279_x64$ fakeroot alien --to-deb opencl-1.2-intel-cpu-3.0.67279-1.x86_64.rpm
    Warning: Skipping conversion of scripts in package opencl-1.2-intel-cpu: postinst prerm
    Warning: Use the --scripts parameter to include the scripts.
    opencl-1.2-intel-cpu-3.0.67279-1.x86_64.rpm is for architecture amd64 ; the package cannot be built on this system


    please help me out

    ResponderEliminar
  11. Looks like you have a 32-bit installation. You need to download the 32-bit packages from Intel's site (or install a 64 bit distro)

    ResponderEliminar
  12. Hi Marcelo, thanks for a such a useful blog post! :)

    I have Ubuntu 12.04 64-bit, and two graphics cards: Intel HD Graphics 4000 and NVIDIA GeForce GT 650N. And after following your instructions, my experience was different than what you described, in two ways.

    One, after I extract the tgz file, I get 5 rpm files instead of just one. They are named:
    opencl-1.2-base-3.0.67279-1.x86_64.rpm,
    opencl-1.2-intel-cpu-3.0.67279-1.x86_64.rpm,
    opencl-1.2-devel-3.0.67279-1.x86_64.rpm,
    opencl-1.2-intel-devel-3.0.67279-1.x86_64.rpm,
    opencl-1.2-intel-mic-3.0.67279-1.x86_64.rpm.

    I installed each of these one after another except the last one. There was no error.

    Secondly, then I tried compiling your example code using the same g++ line you mentioned, but returns an error: Cannot find -lOpenCL. Then I tried to find my libOpenCL.so files, but there weren't any. There is even no /usr/lib64 directory. Why did the installers not install the library files in my machine? Could you please help? I look forward to hearing from you. Thanks!

    ResponderEliminar
  13. Hi Neeraj,
    Looks like Intel has changed the distribution files as you said. You will need to convert all the .rpm files using the "fakeroot alien --to-deb" command and then install all the .deb files. Install all the packages with the command "dpkg -i *deb".

    The one with the libOpenCL.so file is "opencl-1.2-base_3.0.67279-2_amd64.rpm" which, when converted to .deb, shows the following files:

    drwxr-xr-x root/root 0 2013-06-05 10:20 ./
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./etc/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./etc/OpenCL/
    drwxr-xr-x root/root 0 2013-04-29 07:37 ./etc/OpenCL/vendors/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./usr/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./usr/share/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./usr/share/doc/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./usr/share/doc/opencl-1.2-base/
    -rw-r--r-- root/root 183 2013-06-05 10:20 ./usr/share/doc/opencl-1.2-base/changelog.Debian.gz
    -rw-r--r-- root/root 1372 2013-06-05 10:20 ./usr/share/doc/opencl-1.2-base/copyright
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./opt/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./opt/intel/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./opt/intel/opencl-1.2-3.0.67279/
    drwxr-xr-x root/root 0 2013-06-05 10:20 ./opt/intel/opencl-1.2-3.0.67279/lib64/
    -rwxr-xr-x root/root 27008 2013-04-28 12:20 ./opt/intel/opencl-1.2-3.0.67279/lib64/libOpenCL.so.1.2
    lrwxrwxrwx root/root 0 2013-06-05 10:20 ./opt/intel/opencl-1.2-3.0.67279/lib64/libOpenCL.so.1 -> libOpenCL.so.1.2
    lrwxrwxrwx root/root 0 2013-06-05 10:20 ./opt/intel/opencl-1.2-3.0.67279/lib64/libOpenCL.so -> libOpenCL.so.1

    Hope this helps!

    ResponderEliminar
  14. This is the output I get when I run the test code:
    In file included from opencl.cpp:2:0:
    /usr/include/CL/cl.hpp: In function ‘cl_int cl::UnloadCompiler()’:
    /usr/include/CL/cl.hpp:1606:12: error: ‘::clUnloadCompiler’ has not been declared
    /usr/include/CL/cl.hpp: In constructor ‘cl::Image2D::Image2D(const cl::Context&, cl_mem_flags, cl::ImageFormat, size_t, size_t, size_t, void*, cl_int*)’:
    /usr/include/CL/cl.hpp:2365:19: error: ‘::clCreateImage2D’ has not been declared
    /usr/include/CL/cl.hpp: In constructor ‘cl::Image2DGL::Image2DGL(const cl::Context&, cl_mem_flags, GLenum, GLint, GLuint, cl_int*)’:
    /usr/include/CL/cl.hpp:2410:19: error: ‘::clCreateFromGLTexture2D’ has not been declared
    /usr/include/CL/cl.hpp: In constructor ‘cl::Image3D::Image3D(const cl::Context&, cl_mem_flags, cl::ImageFormat, size_t, size_t, size_t, size_t, size_t, void*, cl_int*)’:
    /usr/include/CL/cl.hpp:2464:19: error: ‘::clCreateImage3D’ has not been declared
    /usr/include/CL/cl.hpp: In constructor ‘cl::Image3DGL::Image3DGL(const cl::Context&, cl_mem_flags, GLenum, GLint, GLuint, cl_int*)’:
    /usr/include/CL/cl.hpp:2510:19: error: ‘::clCreateFromGLTexture3D’ has not been declared
    /usr/include/CL/cl.hpp: In member function ‘cl_int cl::CommandQueue::enqueueMarker(cl::Event*) const’:
    /usr/include/CL/cl.hpp:3745:13: error: ‘::clEnqueueMarker’ has not been declared
    /usr/include/CL/cl.hpp: In member function ‘cl_int cl::CommandQueue::enqueueWaitForEvents(const std::vector&) const’:
    /usr/include/CL/cl.hpp:3752:13: error: ‘::clEnqueueWaitForEvents’ has not been declared
    /usr/include/CL/cl.hpp: In member function ‘cl_int cl::CommandQueue::enqueueBarrier() const’:
    /usr/include/CL/cl.hpp:3867:13: error: ‘::clEnqueueBarrier’ has not been declared

    ResponderEliminar
  15. Very nice tutorial, but to run the program properly you must ensure to add the icd loader otherwise the program just doesn't know which platforms are available.

    Another problem is that intel changed the tar.gz file, it now contains 5 different rpms. But you can still use the method which is described above.

    Someone who needs support for the icd-loader could check this tutorial:
    https://gist.github.com/rmcgibbo/6314452

    Have fun!

    ResponderEliminar
  16. hello Marcello, thank you for this post.
    I have a problem : when I compile your example, it returns an error : fatal error: CL/cl.hpp: Aucun fichier ou dossier de ce type
    #include
    ^
    compilation terminated.
    Can you help me plz to figure it out. thank you :)

    ResponderEliminar