An Introduction to CMake and How To use CUDA in PandaRoot with it

As you already might have seen in the last post, I worked on a special thingy during the last few weeks. Implementing CUDA into PandaRoot.

I documented every part extensivly in a GitHub repository. If reading this blog post leaves you curious, head over there for a more complete and in-depth description. Also, my code is now officially checked in to our SVN repo.

Background

PandaRoot is our experiment’s software package. It customizes and greatly expands CERN’s ROOT by two layers: Inter-experiment wide via FairRoot, and for our PANDA needs via PandaRoot.

To build everything, CMake is used.

CMake is a scripting language which generates Makefiles. These, in turn, are used to create binary files. CMake simplifies creating Makefiles for big projects, just like PandaRoot is one. It lets you keep on overview of all the interdependencies and gives the ability to work with structured, but possibly complicated hierarchies. It also allows out-of-source builds1

CMake for C++

Creating a Makefile with CMake for a simple C++ project is as easy as putting this line into a CMakeLists.txt:

After cmake . and make you get an executable plainCMake file. And you’re done.
You find my small exemplary plain CMake project at GitHub.

CMake and CUDA

Generally, using CUDA from CMake is also not very hard. Luckily there is already a package in CMake which finds all the CUDA compilers and libraries and provides lots of macros. Load it into your current CMakeLists.txt by:

Now, creating CUDA binaries is as easy as creating plain C++ binaries before. You just prepend CUDA_ to the usual CMake macros and you’re pretty much done.

There are lots of more settings you can do (like set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --gpu-architecture sm_20) for compiling using Compute Capability 2.0 for double precision support) — they are documented in the FindCUDA.cmake file.

Again, take a look at my GitHub CMake+CUDA example. There’s a lot more explanation and I also show how to use if (CUDA_FOUND) to dynamically steer your compilation into the CUDA way (or not).

CMake for CUDA in PandaRoot

Including a CUDA function into our C++/ROOT using PandaRoot environment is not that easy.

Source files

The trick is to declare the CUDA function as extern, compile them separately and link them to wrapping C++ objects.2

Let’s say, our CUDA kernel and function look like this (I marked the extern line):

Our wrapping C++ class then first has to declare this function as extern as well and wrap a method around it. Like:

CMake

Concerning the CMakeLists.txt you also have to distinguish between a CUDA one and a C++ one.

The CUDA CMakeLists.txt file has to look like before, but instead of generating a binary it should just create a shared object in the end.

In line 1 and 2 the variable PNDCUDAEXAMPLESONAME is introduced. This is convenient so that you just need to define your actual .so name once and can then use it in the current CMakeLists.txt as well as the parent one.

Up there, the important parts of the CMakeLists.txt look like:

First, you add the CUDA containing subdirectories to the CMake chain (line 1). Over there, the CUDA shared object is built. In line 6 you link it to the current C++ object/binary, so that you can actually use it from PandaRoot. Line 3 prevents the current project from being built before its CUDA sub-project — otherwise the CUDA .so file to link with wouldn’t be there.

And that’s it. More or less.

I wrote a lot more on it at the GitHub project. I also explained some skipped pieces and what else you have to change in order for this piece to actually run.


  1. The binary files reside in different directories then the source files. 

  2. This idea is not mine but was already once done in FairRoot. It didn’t compile for me, though. so I decided to do a minimal example of a setup. 

2 Gedanken zu „An Introduction to CMake and How To use CUDA in PandaRoot with it

  1. Pingback: Week #89 | Doktorandi

  2. Pingback: Week #92 | Doktorandi

Kommentare sind geschlossen.