I'm writing this because I believe there is general interest in this subject. I'm not an expert, so errors and mistakes in this post are highly likely. Corrections and improvements are gratefully accepted. Credits for finding these simple but less than obvious procedures go to wizards dipak and Luke Iwanski.
Although Open CL has been supported for quite a while by AMD GPUs, a problem appeared with the introduction of Ubuntu 16.04. If I understand right, prior to Ubuntu 16.04, the Linux kernel supported AMD graphics cards, but then the card support was transferred to the external amdgpu open-source driver. Unfortunately, amdgpu does not support Open CL. Although Open CL is supported by the proprietary driver amdgpu-pro, this driver only supports newer cards, here meaning GPUs implementing the GCN-1.2 architecture or newer.
Examples of GCN-1.x GPU/cards:
GCN-1.0 ("old", ~2011): HD 7750, HD 7770, R7 250X, HD 7850, HD 7870, R9 270X, R9 270, R7 370, HD 7950, R9 280, HD 7970, R9 280X;
GCN-1.1 ("old"): HD 7790, R7 260, R7 260X, R7 360, R9 290, R9 390, R9 290X, R9 390X;
GCN-1.2 ("newer", ~2014): R9 285, R9 380, R9 380X...
Running Open CL on newer cards
A quick glance at the web gives the impression that it is difficult to run Open CL on AMD GPUs, but this isn't true. It is actually quite easy, at least for newer GPUs. Here is how it can be done, starting from an up-to-date vanilla Ubuntu 16.04 LTS installation:
- Download the amdgpu-pro driver from http://support.amd.com/en-us/kb-articles/Pages/AMDGPU-PRO-Install.aspx . Install acoording to the instructions on the site.
- Install the Open CL headers from the Ubuntu repository by
sudo apt install opencl-headers
- Compile your program by the GNU compiler. An appropriate "Hello world" program is the MatrixTranspose example kindly provided by dipak,. It can be compiled by
g++ MatrixTranspose.cpp -L/opt/amdgpu-pro/lib/x86_64-linux-gnu/ -lOpenCL
Running Open CL on old cards
WARNING to relatively inexperienced people like myself: The operations below could trash the system. Make sure there is a backup. Beware that dual-booted Ubuntu 16.04 and 14.04 can sometimes break each other, even if you have separate boot and root partitions!
Running Open CL on old cards is a little bit trickier than on newer cards. For old cards, downgrading to Ubuntu 14.04 is necessary, the kernel of which must be further downgraded to 3.19 (details below). I assume (and have tested the procedure below on) a Ubuntu 14.04 LTS server clean installation. For simplicity, here are the steps in the form of a bash script:
#!/bin/bash -x case $1 in 1) # Install Linux kernel 3.19 sudo apt-get install linux-image-3.19.0-79-generic linux-image-extra-3.19.0-79-generic linux-headers-3.19.0-79-generic ;; 2) # Check current kernel uname -r ;; 3) # Remove it sudo apt-get remove linux-image-$(uname -r) ;; 4) # Update boot sudo update-grub ;; 5) # Reboot sudo reboot ;; 6) # Check that kernel 3.19.0-79-generic is loaded uname -r ;; 7) # Install build-essential and Open CL 1.2 headers sudo apt-get install build-essential ocl-icd-opencl-dev opencl-headers ;; 8) # Download AMD drivers wget --referer=http://support.amd.com https://www2.ati.com/drivers/linux/fglrx_15.302-0ubuntu1_amd64_ub_14.01.deb wget --referer=http://support.amd.com https://www2.ati.com/drivers/linux/fglrx-core_15.302-0ubuntu1_amd64_ub_14.01.deb ;; 9) # Install the downloaded drivers sudo dpkg -i fglrx-core_15.302-0ubuntu1_amd64_ub_14.01.deb fglrx_15.302-0ubuntu1_amd64_ub_14.01.deb ;; 10) # Reboot sudo reboot ;; 11) # Check GPU clinfo ;; 12) # Choose MatrixTranspose directory and compile cd MatrixTranspose g++ MatrixTranspose.cpp -L/usr/lib/x86_64-linux-gnu/ -lOpenCL ;; esac
A few comments: Use by
bash script.sh <step number>
etc. Don't forget to watch the output messages, in particular at step 3. It can happen that another kernel is automatically installed upon removal. Make certain that the Linux kernel is not newer than 3.19 in step 6!
In order to compile the MatrixTranspose program without error messages, a minor change in CLUtil.hpp is necessary. The lines reading
case CL_INVALID_DEVICE_QUEUE: return "CL_INVALID_DEVICE_QUEUE"; case CL_INVALID_PIPE_SIZE: return "CL_INVALID_PIPE_SIZE";
need to be commented out.