Book Image

Hands-On GPU-Accelerated Computer Vision with OpenCV and CUDA

By : Bhaumik Vaidya
Book Image

Hands-On GPU-Accelerated Computer Vision with OpenCV and CUDA

By: Bhaumik Vaidya

Overview of this book

Computer vision has been revolutionizing a wide range of industries, and OpenCV is the most widely chosen tool for computer vision with its ability to work in multiple programming languages. Nowadays, in computer vision, there is a need to process large images in real time, which is difficult to handle for OpenCV on its own. This is where CUDA comes into the picture, allowing OpenCV to leverage powerful NVDIA GPUs. This book provides a detailed overview of integrating OpenCV with CUDA for practical applications. To start with, you’ll understand GPU programming with CUDA, an essential aspect for computer vision developers who have never worked with GPUs. You’ll then move on to exploring OpenCV acceleration with GPUs and CUDA by walking through some practical examples. Once you have got to grips with the core concepts, you’ll familiarize yourself with deploying OpenCV applications on NVIDIA Jetson TX1, which is popular for computer vision and deep learning applications. The last chapters of the book explain PyCUDA, a Python library that leverages the power of CUDA and GPUs for accelerations and can be used by computer vision developers who use OpenCV with Python. By the end of this book, you’ll have enhanced computer vision applications with the help of this book's hands-on approach.
Table of Contents (15 chapters)

A basic program in CUDA C

In this section, we will start learning CUDA programming by writing a very basic program using CUDA C. We will start by writing a Hello, CUDA! program in CUDA C and execute it. Before going into the details of code, one thing that you should recall is that host code is compiled by the standard C compiler and that the device code is executed by an NVIDIA GPU compiler. A NVIDIA tool feeds the host code to a standard C compiler such as Visual Studio for Windows and a GCC compiler for Ubuntu, and it uses macOS for execution. It is also important to note that the GPU compiler can run CUDA code without any device code. All CUDA code must be saved with a *.cu extension.

The following is the code for Hello, CUDA!:

#include <iostream>
__global__ void myfirstkernel(void) {
}
int main(void) {
myfirstkernel << <1, 1 >> >();
printf("Hello, CUDA!\n");
return 0;
}

If you look closely at the code, it will look very similar to that of the simple Hello, CUDA! program written in C for the CPU execution. The function of this code is also similar. It just prints Hello, CUDA! on Terminal or the command line. So, two questions that should come to your mind is: how is this code different, and where is the role of CUDA C in this code? The answer to these questions can be given by closely looking at the code. It has two main differences, compared to code written in simple C:

  • An empty function called myfirstkernel with __global__ prefix
  • Call the myfirstkernel function with << <1,1> >>

__global__ is a qualifier added by CUDA C to standard C. It tells the compiler that the function definition that follows this qualifier should be complied to run on a device, rather than a host. So, in the previous code, myfirstkernel will run on a device instead of a host, though, in this code, it is empty.

Now where will the main function run? The NVCC compiler will feed this function to host the C compiler, as it is not decorated by the global keyword, and hence the main function will run on the host.

The second difference in the code is the call to the empty myfirstkernel function with some angular brackets and numeric values. This is a CUDA C trick to call device code from host code. It is called a kernel call. The details of a kernel call will be explained in later chapters. The values inside the angular brackets indicate arguments we want to pass from the host to the device at runtime. Basically, it indicates the number of blocks and the number of threads that will run in parallel on the device. So, in this code, << <1,1> >> indicates that myfirstkernel will run on one block and one thread or block on the device. Though this is not an optimal use of device resources, it is a good starting point to understand the difference between code executed on the host and code executed on a device.

Again, to revisit and revise the Hello, CUDA! code, the myfirstkernel function will run on a device with one block and one thread or block. It will be launched from the host code inside the main function by a method called kernel launch.

After writing code, how will you execute this code and see the output? The next section describes the steps to write and execute the Hello, CUDA! code on Windows and Ubuntu.

Steps for creating a CUDA C program on Windows

This section describes the steps to create and execute a basic CUDA C program on Windows using Visual Studio. The steps are as follows:

  1. Open Microsoft Visual Studio.
  2. Go to File | New | Project.
  3. Select NVIDIA | CUDA 9.0 | CUDA 9.0 Runtime.
  4. Give your desired name to the project and click on OK.
  5. It will create a project with a sample kernel.cu file. Now open this file by double-clicking on it.
  6. Delete existing code from the file and write the given code earlier.
  7. Build the project from the Build tab and press Ctrl + F5 to debug the code. If everything works correctly, you will see Hello, CUDA! displayed on the command line, as shown here:

Steps for creating a CUDA C program on Ubuntu

This section describes the steps to create and execute a basic CUDA C program on Ubuntu using the Nsight Eclipse plugin. The steps are as follows:

  1. Open Nsight by opening Terminal and typing nsight into it.
  2. Go to File | New |CUDA C/C++ Projects.
  3. Give your desired name to the project and click on OK.
  4. It will create a project with a sample file. Now open this file by double-clicking on it.
  1. Delete the existing code from the file and write the given code earlier.
  2. Run the code by pressing the play button. If everything works correctly, you will see Hello, CUDA! displayed on Terminal as shown here: