Friday 15 September 2017

How to use Intel GPU for desktop display and dedicate Nvidia GPU for CUDA in Ubuntu?

[This solution has been rendered obsolete by the latest nvidia-415 driver, please see my Jan2019 post for the latest solution on this same problem]

Nowadays, most of modern desktop and laptop motherboards have a built-in Intel GPU for graphics display. In Ubuntu, if the desktop display uses Nvidia GPU (`prime-select nvidia`), then:
  1. when you are running CUDA simulations, you will often experience some lags or latency when manipulating with desktop items, e.g., switching to another desktop, maximizing/minimizing windows;
  2. you have less graphics memory for CUDA simulations since many desktop windows programs (including Windows itself) uses GPU memory for graphics acceleration.
The solution to this latency is to dedicate the Intel GPU for desktop display and dedicate the Nvidia GPU for CUDA programs. http://osdf.github.io/blog/intel-integrated-graphics-dedicated-gpu-for-cuda-and-ubuntu-1310.html has given a very sophisticated, complicated and long-winded but nonetheless working solution. We have a much simpler way of doing so.

Assuming you have correctly setup Nvidia driver and CUDA library, and you are able to run desktop and CUDA using your Nvidia GPU. Do the following two steps:
  1. prime-select intel
  2. append the following code in your .profile or .bashrc
if [ `ps aux | grep compiz | wc -l` -ge 2 ]; then
        nvpath=`echo /usr/lib/nvidia-???`
        export LD_LIBRARY_PATH=$nvpath:$LD_LIBRARY_PATH
fi
This will make all desktop 3D accelerations (desktop display programs like Xorg, compiz, and all OpenGL programs) to use Intel GPU, while all CUDA simulation programs (including nvidia-smi) will use Nvidia GPU. Of course, since the above code looks for the process named compiz to determine whether you are already inside desktop environment, thus, if you are not using Unity(3D) desktop, you need to change the process name correspondingly, otherwise, you might end up with a login loop and have to press Ctrl+Alt+F1 to switch to TTY to troubleshoot.

The principle is that in order to use GPU acceleration for CUDA programs (including nvidia-smi), your LD_LIBRARY_PATH must contain /usr/lib/nvidia-???

If later, you need to switch back to use Nvidia GPU for running desktop 3D programs like Blender, you can simply run `prime-select nvidia` and re-login.



The above solution works only on computers whose BIOS supports primary display device selection. Many CUDA-ignorant vendors such as Dell thought that whenever a dedicated GPU is plugged into PCIe, the on-board Intel GPU will never be used. Thus, their BIOS will automatically disable Intel GPU if a dedicated GPU is plugged into PCIe.

On such computers, you will see a black screen after doing the above steps. You have to forcefully set the PCI BusID of your desktop display device. To do so, first you need to obtain the PCI BusID of your Intel graphics card by running lspci:
00:02.0 Display controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)
01:00.0 VGA compatible controller: NVIDIA Corporation GM206 [GeForce GTX 960] (rev a1)
Take note of the BusID of the Intel graphics card, i.e., 00:02.0. After that, you need to edit your /etc/X11/xorg.conf as below:
Section "Device"
        Identifier "intel"
        Driver "intel"
        BusID "PCI:0:2:0"
EndSection

Section "Screen"
        Identifier      "intel"
        Device          "intel"
EndSection
By doing so, you force your display device to use Intel driver on Intel GPU's PCI BusID.

Now, you can see your screen and enter desktop. But you will find out that you cannot run any CUDA program even with LD_LIBRARY_PATH=/usr/lib/nvidia-###. The reason is because Nvidia driver is loaded but never connected. You must first run the following as root once:
LD_LIBRARY_PATH=/usr/lib/nvidia-### nvidia-smi
After that, everything will work as usual. You can put the above line in your /etc/rc.local to make it auto-run every time the machine reboots.

One drawback of such a configuration is that you will not be able to see your screen before reaching the login screen unless you plug your monitor cable into Nvidia card; moreover, once you have reached the login screen, you won't be able to see TTY by pressing Ctrl+Alt+F1, regardless of whether you plug monitor into motherboard or Nvidia card.
The other drawback of this is that you cannot run from command line any GUI program that uses hardware acceleration, e.g., SDL2, OpenGL, etc. This is because your desktop is using Intel GPU, thus, any desktop GUI program that uses hardware acceleration must also use Intel GPU. So the solution is to remove /usr/lib/nvidia-### from LD_LIBRARY_PATH when running those hardware accelerated GUI programs.