Wednesday, July 30, 2014

Getting Qt to play nice with CUDA (Via CMake)

For a while, I tried to get qmake to compile and run CUDA kernels as part of my Qt project. I still think this is achievable, but I got frustrated with it and tried a different approach, as suggested by a coworker and friend of mine, whom we will call Bob :)  He was a huge help with this, and I decided to pass it on and document how it was done. 

First off, we are not creating a typical Qt project. You need to have CMake installed and select "Non-Qt Project" from the Qt templates:


Do not fret, however, as you will still be able to use all the Qt GUI functionality. We are just using CMake instead of qmake to build our project. Now we have to write the CMakeLists.txt file, which will tell CMake how to link everything and build the project correctly.

You can rewrite the 3 or so lines that were generated automatically. We just need the minimum required version of CMake, and to set our project's executable name and store it in a variable:
 cmake_minimum_required(VERSION 2.8.8)  
 set(EXECUTABLE_NAME <your executable name>)  
 project(${EXECUTABLE_NAME})  

Next, we deal with the moc files Qt creates (MOC stands for Meta Object Compiler in case anyone was wondering):
 # Tell CMake to run moc when necessary:  
 set(CMAKE_AUTOMOC ON) 
  
 # As moc files are generated in the binary dir, tell CMake  
 # to always look for includes there:  
 set(CMAKE_INCLUDE_CURRENT_DIR ON)  

We then tell CMake to look for the packages we will need, namely Qt5 Widgets, OpenGL, and of course CUDA:
 find_package(Qt5Widgets REQUIRED)  
 find_package(Qt5OpenGL REQUIRED)  
 find_package(CUDA REQUIRED)  

Add all the sources so they show up in Qt Creator:
 #Qt UI stuff...  
 qt5_wrap_ui(UI_HEADERS mainwindow.ui)  

 #Non-UI headers...  
 set(HEADERS  
       mainwindow.h  
       <stuff.h>  
   )  

 #ALL the source files  
 set(SOURCES  
       main.cpp  
       mainwindow.cpp  
       <stuff.cpp>  
   )  

Note: you can set nvcc compiler flags, but I have not needed to for this example. Here is how:
 set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-O3 -gencode arch=compute_20,code=sm_20)  

Next, compile the CUDA objects. You can actually have multiple calls to cuda_compile and build different objects with different flags. But in this example, we only have one.
 cuda_compile(CUDA_OBJECTS cudakernel.cu)  

Pass additional compiler flags (non-nvcc):
 set(EXTRA_CXX_FLAGS "--std=c++11" CACHE STRING "common C++ build flags")  
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXX_FLAGS}")  

Finally, link everything together: your executable, additional libraries, and Qt modules all use their own CMake commands to link properly:
 #Build the rest of the executable.  
 add_executable(${EXECUTABLE_NAME} ${SOURCES} ${HEADERS} ${UI_HEADERS} ${CUDA_OBJECTS})  

 #Remember dependencies!  
 target_link_libraries(${EXECUTABLE_NAME} GL ${CUDA_LIBRARIES})  

 #Add the Qt stuff.  
 qt5_use_modules(${EXECUTABLE_NAME} Widgets OpenGL)  

And that's it! Put all of that together in the CMakeLists.txt file and you'll be good to go. Now I can have my fun with Qt Creator and CUDA kernels :D

If anyone has any questions or issues with this, let me know in the comments and I will do my best to help.

Wednesday, May 21, 2014

Finally! CUDA works, the fun may begin

 It took me longer than anticipated, but I finally got it working! (with some help and a lot of web searching) But playing around with GPU programming is a for-fun side project for me, so please forgive the slow updates.

Sytem setup:
Ubuntu 14.04 64bit (fresh install)
Graphics card is an NVidia GeForce GTX Titan

The Titan being a relatively new card, it is a bit particular about its drivers. The Ubuntu kernel Nouveau driver obviously doesn't work for it, and you wouldn't be running CUDA with the kernel drivers anyway. I ended up sticking with the 331.62 NVidia driver version, because that is what comes with the CUDA installer. A newer version would probably have worked as well. The bottom line is, the Titan needs newer drivers. And, do yourself a favor and ditch Nouveau ;)

What didn't work
I broke the GUI trying various things that didn't work, so I'll talk about them here, to hopefully save you the trouble.

First off, when you try running nvcc, the CUDA compiler, you'll be told that you don't have it and you need to install it by running sudo apt-get install cuda-toolkit to get it. Don't do that! When you then try to run your cuda code and check for errors, you will get "No cuda-capable device detected". And you'll have no idea why, because you have a Titan card and that surely has to be cuda-capable! It is. You just don't have cuda-driver compatibility. 

Another thing you shouldn't do is run sudo apt-get install nvidia-current. This and having the cuda-toolkit installed is what breaks everything. 

What does work
This is how to do it right, step by step.

0. Purge all existing nvidia drivers, just in case.
 sudo apt-get remove --purge nvidia*  
 sudo apt-get clean  


1. Install build-essential if you don't already have it.
 sudo apt-get update  
 sudo apt-get install build-essential  

2. Download the cuda6 installer and unpack it.

I went with version 6.0.37, which can be found here:
http://developer.download.nvidia.com/compute/cuda/6_0/rel/installers/cuda_6.0.37_linux_64.run

Then, unpack it:
 mkdir ~/Downloads/nvidia_installers;  
 cd ~/Downloads  
 ./cuda_6.0.37_linux_64.run -extract=~/Download/nvidia_installers;  
I found that trying to install the whole thing at once also causes problems, so it is safer to unpack it.

3. Switch to terminal mode, turn off the X server, and install the graphics driver

Ctrl+Alt+F1 to switch to the terminal. 
 cd ~/Downloads/nvidia_installers;  
 sudo service lightdm stop  
 sudo killall Xorg  
 sudo ./NVIDIA-Linux-x86_64-331.62.run   
If the killall command doesn't work, don't worry about it. Stopping lightdm is the important part.

The driver installer will turn off and blacklist Nouveau and should then install without issues. Once installation is complete, you can turn on the driver and return to the graphical interface to install CUDA.
 sudo modprobe nvidia  
 sudo service lightdm restart  
But I preferred to reboot, like so: sudo reboot

4. Install CUDA and the Samples, then make sure everything works
 sudo ./cuda-linux64-rel-6.0.37-18176142.run  
 sudo ./cuda-samples-linux-6.0.37-18176142.run  


To check if this works, run the deviceQuery sample:
 cd /usr/local/cuda/samples  
 cd 1_Utilities/deviceQuery  
 make  
 ./deviceQuery    
You should get a screenfull of information about your graphics device. If you do, it means your drivers and CUDA are working properly.

5. Add the CUDA binaries to your PATH

This tripped me up. When I went back and tried to compile my example code, I was again told that I don't have nvcc installed. What gives? Well, you just need to add it to the PATH. Simple.

To do this, you'll have to edit .bashrc. I also added a line to ./bash_profile to make sure ./bashrc actually gets used as the bash profile.
 cd ~  
 vi .bashrc  
 //add the line: export PATH=/usr/local/cuda-6.0/bin:$PATH  
 vi .bash_profile  
 //add the line: source ./bashrc  
Restart the terminal and make sure which nvcc returns /usr/local/cuda-6.0/nvcc.
_________________________________________________________________________________


Now that I was finally good to go, I computed the cubes of 64 numbers (0-64) - in parallel... on the GPU! On a device capable of and designed for handling thousands of threads. Yes, it was silly, because "the GPU doesn't even get out of bed in the morning for less than 500 threads!" But it proved that I can compile and run cuda code now, so it made me happy :)

Source: http://askubuntu.com/questions/451672/installing-and-testing-cuda-in-ubuntu-14-04

Friday, May 9, 2014

Welcome to my world!

Greetings, wanderer of the Internets! And welcome to my little corner of this vast world, a place of fun, insanity and... code - well, mostly code and tech-related things.

I made this blog with the initial intention of documenting my own adventures and journey of learning CUDA, but I may end up posting other fun stuff as well. We shall see where this takes me.

Early next week I'll post about setting up the CUDA environment on Ubuntu 14.04. Until then, have a nice life! :)