Today, we are focusing on a specific configuration: a laptop with both Intel CPU/GPU and a discrete nVidia GPU, managed by the Optimus technology, and Ubuntu 16.04 LTS installed.
Disclaimer: it seems that, due to Nvidia Optimus, there is no way to use both integrated GPU and discrete GPU at the same time. I haven't tested the combination CPU/discrete GPU yet. So, in this article I'll briefly explain how to install the correct drivers for each device, and then to switch between those from Intel and those from Nvidia.
First: let me explain how an OpenCL host software works. An executable is dynamically linked to a special library, named libOpenCL.so, that is called ICD Loader. ICD stands for Installable Client Library: this loader, on Linux, checks for .icd files in /etc/OpenCL/vendors. Each .icd file is a text file which contains a single line: the full path of a platform-specific OpenCL library. So, on our laptop, we should have at least 2 .icd files: one for Nvidia-specific OpenCL libraries, and one for Intel-related devices instead. The loader let the host program access each available device that is reachable from the given set of libraries/drivers.
In OpenCL terminology, each driver pointed by an .icd file corresponds to an OpenCL Platform, and each device that is supported by that driver is an OpenCL Device.
In OpenCL terminology, each driver pointed by an .icd file corresponds to an OpenCL Platform, and each device that is supported by that driver is an OpenCL Device.
Installation of core loader, drivers, headers
We need to install the ICD loader and a simple diagnostic/info tool:
sudo apt install -y ocl-icd-libopencl1 clinfo
Next, we install ICDs for Intel and Nvidia GPUs:
sudo apt install -y beignet-opencl-icd nvidia-opencl-icd
Finally, we'll fetch the CPU driver from the Intel website, and we'll manually install it:
wget https://software.intel.com/sites/default/files/managed/8e/5c/SRB3.1_linux64.zip
mkdir temp
unzip SRB3.1_linux64.zip -d ./temp
cd temp
for i in *.tar.xz; do tar -xJf $i; done
sudo rsync -av ./opt /opt
sudo rsync -av ./etc /etc
cd ..
rm -R temp
Now, the final magic: go to the /etc/OpenCL/vendors folder, with root privileges. You'll see two .icd files. Rename the beignet one to intel_gpu.icd and the nvidia one to nvidia_gpu.icd; finally, create a new text file called intel_cpu.icd with the line ".../libintelocl.so"
Try the command "clinfo". It should be end in a segfault or in weird errors naming the X server and something about Dri2 access. If all platforms, (Intel CPU, Intel GPU, Nvidia GPU) are correctly detected, it means that you are luckier than me. In my case (Intel i7-4710MQ and Nvidia GTX 960 on a Clevo barebone 13' laptop), the already-mentioned errors occur.
Now we update the OpenCL headers with the last version from Kronos GitHub Repo:
Now we update the OpenCL headers with the last version from Kronos GitHub Repo:
sudo rm -R /usr/local/include/CL
sudo mkdir /usr/include/CL
sudo wget https://github.com/KhronosGroup/OpenCL-Headers/archive/master.zip -P /usr/include/CL
sudo unzip -j -o /usr/include/CL/master.zip -d /usr/include/CL
sudo rm /usr/include/CL/master.zip
sudo wget https://github.com/KhronosGroup/OpenCL-CLHPP/archive/master.zip -P /usr/include/CL
sudo unzip -j -o /usr/include/CL/master.zip "*input_cl2.hpp" -d /usr/include/CL
sudo mv /usr/include/CL/input_cl2.hpp /usr/include/CL/cl2.hpp
sudo rm /usr/include/CL/master.zip
Solving troubles with Optimus
The solution is quite simple. If you want to work with intel devices, you have to install the official Nvidia Prime package (it's a kind of switcher between Intel and Nvidia drivers):sudo apt install -y nvidia-prime
Then, to use OpenCL on Nvidia card:
sudo prime-select nvidia
sudo mv /etc/OpenCL/vendors/intel_cpu.icd /etc/OpenCL/vendors/intel_cpu.icd_disabled
sudo mv /etc/OpenCL/vendors/intel_gpu.icd /etc/OpenCL/vendors/intel_gpu.icd_disabled
sudo mv /etc/OpenCL/vendors/nvidia_gpu.icd_disabled /etc/OpenCL/vendors/nvidia_gpu.icd
# now you have: intel_cpu.icd_disabled, intel_gpu.icd_disabled, nvidia_gpu.icd
clinfo --list # this should detect correctly only your Nvidia GPU now
Then, to use OpenCL on Intel devices:
sudo prime-select intel
sudo mv /etc/OpenCL/vendors/intel_gpu.icd_disabled /etc/OpenCL/vendors/intel_gpu.icd
sudo mv /etc/OpenCL/vendors/intel_cpu.icd_disabled /etc/OpenCL/vendors/intel_cpu.icd
sudo mv /etc/OpenCL/vendors/nvidia_gpu.icd /etc/OpenCL/vendors/nvidia_gpu.icd_disabled
# now you have: intel_cpu.icd, intel_gpu.icd, nvidia_gpu.icd_disabled
clinfo --list # this should detect correctly only your CPU and the built-in GPU