OpenCL on Intel HD / Iris graphics on Linux

Brian KloppenborgOpenCL 19 Comments

Under Windows and Mac the Intel GPU drivers include OpenCL support; however, on Linux OpenCL on Intel GPUs is implemented through an open source project called Beignet (pronnounced like “ben-yay”, a type of French pastry akin to a what we would call a “fritter” in English). Below I have written a step-by-step guide on how you can get Beignet running on an Ubuntu 14.10 system which has an Intel 3rd, 4th, or 5th generation Intel processor. Instructions for other variants of Linux will be similar, except for the commands to install the prerequisite packages.

There are several little caveats which need to be discussed up front. Foremost, the Beignet project supports the following hardware:

  • 3rd Generation Intel Core Processors
  • Intel “Bay Trail” platforms with Intel HD Graphics
  • 4th Generation Intel Core Processors (requires a kernel patch be applied for shared memory!)
  • 5th Generation Intel Core Processors “Broadwell”.

There are also a few noteworthy issues of which you should be aware:

  • If your computer is running a Linux kernel in the 3.15 or 3.16 branch, you will need to disable some register whitelist functionality every time you reboot your system. This can be accomplished by running echo 0 > /sys/module/i915/parameters/enable_cmd_parser as root.
  • 4th Generation Intel Processors (i.e. i3/5/7-4xxx) require a kernel patch for shared/local memory to function.
  • There is no double precision support
  • OpenGL-OpenCL interop via cl_khr_gl_sharing is not supported

There are additional release notes that can be found on the Beignet project page.

Installing prerequisites

sudo apt-get install build-essential g++ cmake 
sudo apt-get install clang libclang-3.5-dev libclang-dev libclang1
sudo apt-get install ocl-icd-opencl-dev ocl-icd-libopencl1

Note, if you are on a Ubuntu 14.04 system, you should install libclang-3.4-dev instead, then run update-alternatives to point llvm-link and llvm-as to the correct version. The latter can be accomplished using the following commands:

sudo update-alternatives --install /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-3.4 34
sudo update-alternatives --install /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-3.4 34  

If you want to use the standard OpenCL ICD loader, you will also need to install these packages:

sudo apt-get install opencl-headers ocl-icd-dev ocl-icd-libopencl1    

I would also recomment you install the clinfo program so that you can verify that your installation is successful:

sudo apt-get install clinfo    

Check out and compile Beignet

git clone git://anongit.freedesktop.org/beignet
cd beignet
git checkout Release_v1.0.0
mkdir build
cd build
cmake ..   

NOTE: There may be newer releases of Beinget. To find releases type git branch -a on the console and pick the highest release version number.

During the CMake stage, ensure that the OCL ICD header file is installed, otherwise the library will not create an installable client driver. If everything went fine, go ahead and compile the source using

make    

(Note, you can do make -jN with N > 1 to do a parallel build.)
Next we verify that Beignet is functioning correctly on your hardware by running unit tests. These can be found in the utest folder. The unit tests require some enviornmental variables be set prior to invocation:

cd utests
source setenv.sh
./utest_run   

If a significant fraction of the unit tests fail and you have a 3.15 or 3.16 kernel, you need to disable register whitelisting using a command similar to the following:

sudo su
echo 0 > /sys/module/i915/parameters/enable_cmd_parser
exit    

and try re-running the tests. Please note that this change is not permanent and you will need to re-run it if you reboot your system. Alternatively, you could add this command to a startup script. The Beignet release notes mention there is a kernel patch to fix this issue which you could backport if you so desired.

If most of the tests pass, but those that involve local memory (~20-30 of the tests) fail, you will need to apply the kernel patch listed below.

If all was well, install Beignet to your system:

sudo make install   

You can see a list of installed software in the install_manifest.txt file in the build directory.

Verify Beignet is installed

In a terminal run the clinfo program. You should see something like this:

$ clinfo
...      
Platform Name:              Intel Gen OCL Driver
Number of devices:          1
Device Type:                CL_DEVICE_TYPE_GPU
...
Name:                       Intel(R) HD Graphics Haswell GT2 Desktop
Vendor:                     Intel
Device OpenCL C version:    OpenCL C 1.2 beignet 0.9.1
Driver version:             0.9.1
Profile:                    FULL_PROFILE
Version:                    OpenCL 1.2 beignet 0.9.1
Extensions:                 cl_khr_global_int32_base_atomics 
                            cl_khr_global_int32_extended_atomics 
                            cl_khr_local_int32_base_atomics 
                            cl_khr_local_int32_extended_atomics 
                            cl_khr_byte_addressable_store cl_khr_icd   

Take note that the Intel OpenCL driver is loaded for a GPU device using beignet. This indicates the Installable Client Driver (ICD) is correctly installed. Also note the extensions listed.

Applying the kernel patch to enable OpenCL shared local memory.

If you are using Beignet on a 4th generation Intel processor, you will need to apply a kernel patch to enable shared/local memory. This is a fairly lengthy process that will require at least 70 GB of hard disk space and perhaps an hour of compilation time if the build is executed in parallel.

In the next few paragraphs I’ll walk you through how you can apply the kernel patch. I have based my instructions on the kernel compilation instructions for Ubuntu. Instructions for other variants of Linux will be significantly different.

Install prerequisites:

sudo apt-get build-dep linux-image-`uname -r`    

Make a working directory for the kernel somewhere and download the source

mkdir kernel
cd kernel
apt-get source linux-image-`uname -r`    

Next we see if we can automatically apply the patch. First download the patch:

wget https://01.org/sites/default/files/disable-batchbuffer-security.patch    

Now cd into the kernel directory:

cd linux-3.16.0    

Check some details about the patch

git apply --stat ../disable-batchbuffer-security.patch    

Try automatically applying the patch:

git apply --check ../disable-batchbuffer-security.patch    

If it automatically applies with no errors, just apply it:

git apply ../disable-batchbuffer-security.patch    

If it did not work (as was the case on my system), the change is fairly simple. Open the drivers/gpu/drm/i915/i915_gem_execbuffer.c file in an editor:

gedit drivers/gpu/drm/i915/i915_gem_execbuffer.c   

In the i915_gem_do_execbuffer function, find the following code:

flags = 0;
if (args->flags & I915_EXEC_SECURE) {
    if (!file->is_master || !capable(CAP_SYS_ADMIN))
        return -EPERM;    

And add the line flags |= I915_DISPATCH_SECURE; as follows:

flags = 0;
flags |= I915_DISPATCH_SECURE;
if (args->flags & I915_EXEC_SECURE) {
    if (!file->is_master || !capable(CAP_SYS_ADMIN))
        return -EPERM;  

This was inserted on line 998 for me. Save the file. Now we need to compile and install the modified kernel.

Now we build the new kernel. Run the following commands from within the kernel source directory:

fakeroot debian/rules clean
DEB_BUILD_OPTIONS=parallel=8 fakeroot debian/rules binary-headers binary-generic    

This will build some Debian packages and place them in the directory above the kernel source root.

After the kernel has compiled, install it:

cd ../ (or go back into the kernel directory)
sudo dpkg -i linux-headers-3.16.0-29-generic_3.16.0-29.54_amd64.deb 
sudo dpkg -i linux-image-3.16.0-29-generic_3.16.0-29.54_amd64.deb    

(you might have to change the numeric kernel version to match what you compiled) Now add the kernel to the boot options:

sudo update-grub
sudo reboot    

Now go back and re-run the Beignet unit test framework from above. With any luck everything will work fine.

Comments 19

  1. Pingback: OpenCL on Intel HD / Iris graphics on Linux • Atlanta Tech Blogs

  2. Thank you very so much for this!

    I had to fight a bit with my llvm an clang setup on Ubuntu 14.10. Make sure to install everything in version 3.5 llvm-3.5 clang-3.5, and so on. Then run update-alternatives so cmake and make does not complain about missing binaries, you will need llvm-config, clang, llvm and perhaps other. Also, it is so important that you install ocl-icd-dev,

    ocl-icd-libopencl1 and ocl-icd-opencl-dev otherwise nothing will link.

    If you installed AMD or Intel SDK/runtimes, make sure to delete them prior to anything, and force reinstall of ocl-* since the Intel and AMD stuff break your env.

  3. Hello there,
    thank you both for the guide and the advices…greatly appreciated!
    However, I’m still in trouble since I cannot get my GPU working with OpenCL:
    I followed all the steps in this tutorial, but when I run clinfo it returns that the only
    available device is my Intel Core i7-4712MQ CPU, and the HD4600 iGPU is not given.
    My system is a Linux Mint 17 workstation with 3.16.0-38-generic kernel, rebuilt for the 3.15/16 kernel issues,

    and with the register whitelist patch applied.

    I had intel SDK installed, and that was the error..I uninstalled it and now clinfo says that libOpenCL.so.1 is missing (however I have plenty of libOpenCL in /etc/alternatives or /usr/lib/i386-linux-gnu or /usr/lib/x86_64-linux-gnu)…

    Many thanks in advance, any help would be appreciated!
    Stefano

    1. Perhaps the Intel SDK overwrote the system-default OpenCL Installable Client Drive (ICD) loader with one for the Intel CPU. Could you try reinstalling the OpenCL ICD stuff (opencl-headers, opencl-icd-libopencl1) using dpgk-reconfigure?

  4. I have a Ubuntu 14.04 64 bit machine with Intel I7 4770 CPU that I need GPU support – so I am trying to install and use Beignet.

    I am running make and getting the error:

    fatal error: malformed block record in PCH file

    – for the file beignet.local.pch.

    Any ideas how to fix this error?

  5. Hi thanks a ton for the steps.
    I am stuck however with the following error when I run utests

    builtin_acos_float()Failed: set OCL_KERNEL_PATH

    I am on 14.04 and this is what I have for clang
    clang install
    clang-3.4 install
    libclang-3.4-dev install
    libclang-common-3.4-dev install
    libclang-dev install
    libclang1:amd64 install
    libclang1-3.4:amd64 install

    run2@run2:~/beignet/beignet/build/utests$ sudo ./utest_run
    platform number 1
    platform_profile “FULL_PROFILE”
    platform_name “Intel Gen OCL Driver”
    platform_vendor “Intel”
    platform_version “OpenCL 1.2 beignet 1.0.0 (git-59142eb)”
    platform_extensions “cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_byte_addressable_store cl_khr_icd”
    device_profile “FULL_PROFILE”
    device_name “Intel(R) HD Graphics Haswell GT2 Desktop”
    device_vendor “Intel”
    device_version “OpenCL 1.2 beignet 1.0.0 (git-59142eb)”
    device_extensions “cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_byte_addressable_store cl_khr_icd”
    device_opencl_c_version “OpenCL C 1.2 beignet 1.0.0 (git-59142eb)”
    21 image formats are supported
    [CL_R CL_UNORM_INT8]
    [CL_R CL_UNORM_INT16]
    [CL_R CL_SIGNED_INT8]
    [CL_R CL_SIGNED_INT16]
    [CL_R CL_SIGNED_INT32]
    [CL_R CL_UNSIGNED_INT8]
    [CL_R CL_UNSIGNED_INT16]
    [CL_R CL_UNSIGNED_INT32]
    [CL_R CL_HALF_FLOAT]
    [CL_R CL_FLOAT]
    [CL_RGBA CL_UNORM_INT8]
    [CL_RGBA CL_UNORM_INT16]
    [CL_RGBA CL_SIGNED_INT8]
    [CL_RGBA CL_SIGNED_INT16]
    [CL_RGBA CL_SIGNED_INT32]
    [CL_RGBA CL_UNSIGNED_INT8]
    [CL_RGBA CL_UNSIGNED_INT16]
    [CL_RGBA CL_UNSIGNED_INT32]
    [CL_RGBA CL_HALF_FLOAT]
    [CL_RGBA CL_FLOAT]
    [CL_BGRA CL_UNORM_INT8]
    builtin_acos_float()Failed: set OCL_KERNEL_PATH. This is where the kiss kernels are (-1)

    summary:
    ———-
    total: 700
    run: 1
    pass: 0
    fail: 1
    pass rate: 0.998571

    I have tried lot of things now but nothing works.

    Do you have an idea where I might have the problem ?

    Btw the path is set properly

    run2@run2:~/beignet/beignet/build/utests$ echo $OCL_KERNEL_PATH
    /home/run2/beignet/beignet/utests/../kernels

    Thanks regards
    Deb

        1. Humm. The error simply indicates the user doesn’t have the variable in their path. I suspect this is because you are sourcing the setenv.sh file as your user, then running the program as root. Try this instead:

          cd build/utests
          source setenv.sh
          ./utest_run

          Notice I didn’t use sudo when running the unit tests. It should execute fine (although on Haswell you may need to apply the kernel patch for the local memory tests to pass). Also, you may want to check out the `Release_v1.1` branch as this is the most recent stable version.

          1. Hey – thanks a lot for that pointer. It was indeed env problem within sudo. I could not run it out of sudo as I got unknown device error in that case. The problem got resolved by using sudo -E ./utest_run

          2. Ok – I did the recompile and kernerl update but I still get 18 failed (same as before kernel update) . Some local memory and some copy stuff. So – any idea how to check if the kernel update is applied properly ?

            compiler_atomic_functions() [FAILED]
            Error: ((int *)buf_data[0])[i] == cpu_dst[i]
            at file /home/run2/beignet/beignet/utests/compiler_atomic_functions.cpp, function compiler_atomic_functions, line 92
            compiler_async_copy_char2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_char2, line 46
            compiler_async_copy_uchar2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_uchar2, line 47
            compiler_async_copy_short2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_short2, line 48
            compiler_async_copy_ushort2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_ushort2, line 49
            compiler_async_copy_int2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_int2, line 50
            compiler_async_copy_uint2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_uint2, line 51
            compiler_async_copy_long2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_long2, line 52
            compiler_async_copy_ulong2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_ulong2, line 53
            compiler_async_copy_float2() [FAILED]
            Error: dst[i] == src[i]
            at file /home/run2/beignet/beignet/utests/compiler_async_copy.cpp, function compiler_async_copy_float2, line 54
            compiler_async_stride_copy() [FAILED]
            Error: dst[i + 0] == (char)(src[i + 0] + 3)
            at file /home/run2/beignet/beignet/utests/compiler_async_stride_copy.cpp, function compiler_async_stride_copy, line 36
            compiler_insn_selection_min() [SUCCESS]
            compiler_insn_selection_max() [SUCCESS]
            compiler_insn_selection_masked_min_max() [SUCCESS]
            compiler_load_bool_imm() [FAILED]
            Error: dst[i] == copiesPerWorkItem
            at file /home/run2/beignet/beignet/utests/compiler_load_bool_imm.cpp, function compiler_load_bool_imm, line 25
            compiler_global_memory_barrier() [SUCCESS]
            compiler_local_memory_two_ptr() [FAILED]
            Error: dst[i+j] == (gid&~0xf) + 15-tid + 15-tid
            at file /home/run2/beignet/beignet/utests/compiler_local_memory_two_ptr.cpp, function compiler_local_memory_two_ptr, line 45
            compiler_local_memory_barrier() [FAILED]
            Error: dst[i+j] == 15-j
            at file /home/run2/beignet/beignet/utests/compiler_local_memory_barrier.cpp, function compiler_local_memory_barrier, line 42
            compiler_local_memory_barrier_wg64() [FAILED]
            Error: dst[i+j] == 63-j
            at file /home/run2/beignet/beignet/utests/compiler_local_memory_barrier_wg64.cpp, function compiler_local_memory_barrier_wg64, line 42
            compiler_local_memory_barrier_2() [FAILED]
            Error: dst[i+j] == locals[0] – 1 -j
            at file /home/run2/beignet/beignet/utests/compiler_local_memory_barrier_2.cpp, function compiler_local_memory_barrier_2, line 25
            compiler_local_slm() [FAILED]
            Error: ((uint32_t*)buf_data[0])[i] == (i%16 + 2 + 1+ i/16)
            at file /home/run2/beignet/beignet/utests/compiler_local_slm.cpp, function compiler_local_slm, line 14

  6. Pingback: libclc: nvptx 后端 [FreeBSD OpenCL] | Ixdroid FreeBSD

  7. Hi, I am installing beignet on linux 14.04 with 4.2 kernel . But when i launch ./utest_run I have errors : [FAILED]
    Error: error calling cl_kernel_init with error CL_INVALID_CONTEXT

    I don’t know how to solve it and if it is link with the kernel version.
    Thank you,

  8. Thank you for the detailed instructions. I’ve followed them until “cmake ..”, in Linux Mint 17.3 (based on Ubuntu 14.04), and got this error:

    user@user-hp ~/Documentos/beig/beignet/build $ cmake ..
    — The C compiler identification is GNU 4.8.4
    — The CXX compiler identification is GNU 4.8.4
    — Check for working C compiler: /usr/bin/cc
    — Check for working C compiler: /usr/bin/cc — works
    — Detecting C compiler ABI info
    — Detecting C compiler ABI info – done
    — Check for working CXX compiler: /usr/bin/c++
    — Check for working CXX compiler: /usr/bin/c++ — works
    — Detecting CXX compiler ABI info
    — Detecting CXX compiler ABI info – done
    — Found PkgConfig: /usr/bin/pkg-config (found version “0.26”)
    — Building mode: RelWithDebInfo
    — LLVM llvm-config found at: /usr/bin/llvm-config-3.4
    — find unstable LLVM version 3.4
    — Looking for XOpenDisplay in /usr/lib/x86_64-linux-gnu/libX11.so
    — Looking for XOpenDisplay in /usr/lib/x86_64-linux-gnu/libX11.so – found
    — Looking for gethostbyname
    — Looking for gethostbyname – found
    — Looking for connect
    — Looking for connect – found
    — Looking for remove
    — Looking for remove – found
    — Looking for shmat
    — Looking for shmat – found
    — Found X11: /usr/lib/x86_64-linux-gnu/libX11.so
    — Looking for XLib – found
    — checking for module ‘libdrm’
    — package ‘libdrm’ not found
    CMake Error at /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:283 (message):
    A required package was not found
    Call Stack (most recent call first):
    /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:337 (_pkg_check_modules_internal)
    CMakeLists.txt:125 (pkg_check_modules)

    — Looking for DRM – not found
    — checking for module ‘libdrm_intel>=2.4.52’
    — package ‘libdrm_intel>=2.4.52’ not found
    CMake Error at CMakeLists.txt:170 (MESSAGE):
    Looking for DRM Intel (>= 2.4.52) – not found

    — Configuring incomplete, errors occurred!
    See also “/home/user/Documentos/beig/beignet/build/CMakeFiles/CMakeOutput.log”.

    The system complains about a missing dependency, ‘libdrm_intel>=2.4.52’. I’ve checked the version installed in my computer with dpkg:

    user@user-hp ~/Documentos/beig/beignet/build $ dpkg -s libdrm-intel1
    Package: libdrm-intel1
    Status: install ok installed
    Priority: optional
    Section: libs
    Installed-Size: 191
    Maintainer: Ubuntu Developers
    Architecture: amd64
    Multi-Arch: same
    Source: libdrm
    Version: 2.4.67-1ubuntu0.14.04.1
    Depends: libc6 (>= 2.17), libdrm2 (>= 2.4.38), libpciaccess0
    Pre-Depends: multiarch-support
    Description: Userspace interface to intel-specific kernel DRM services — runtime
    This library implements the userspace interface to the kernel DRM
    services. DRM stands for “Direct Rendering Manager”, which is the
    kernelspace portion of the “Direct Rendering Infrastructure” (DRI).
    The DRI is currently used on Linux to provide hardware-accelerated
    OpenGL drivers.
    Homepage: http://cgit.freedesktop.org/mesa/drm/
    Original-Maintainer: Debian X Strike Force

    So it shoud have worked, as 2.4.67 > 2.4.52. I suspect the problem is in the naming of the packages. cmake seeks ‘libdrm_intel’, while the repository presents “libdrm-intel”, hyphen instead of underline. Is there some fix for this?

Leave a Reply

Your email address will not be published. Required fields are marked *