OpenCL is a complex subject. To code even the simplest of applications, a developer needs to understand host programming, device programming, and the mechanisms that transfer data between the host and device. The goal of this book is to show how these tasks are accomplished and how to put them to use in practical applications.
The format of this book is tutorial-based. That is, each new concept is followed by example code that demonstrates how the theory is used in an application. Many of the early applications are trivially basic, and some do nothing more than obtain information about devices and data structures. But as the book progresses, the code becomes more involved and makes fuller use of both the host and the target device. In the later chapters, the focus shifts from learning how OpenCL works to putting OpenCL to use in processing vast amounts of data at high speed.
In writing this book, I’ve assumed that readers have never heard of OpenCL and know nothing about distributed computing or high-performance computing. I’ve done my best to present concepts like task-parallelism and SIMD (single instruction, multiple data) development as simply and as straightforwardly as possible.
But because the OpenCL API is based on C, this book presumes that the reader has a solid understanding of C fundamentals. Readers should be intimately familiar with pointers, arrays, and memory access functions like malloc and free. It also helps to be cognizant of the C functions declared in the common math library, as most of the kernel functions have similar names and usages.
OpenCL applications can run on many different types of devices, but one of its chief advantages is that it can be used to program graphics processing units (GPUs). Therefore, to get the most out of this book, it helps to have a graphics card attached to your computer or a hybrid CPU-GPU device such as AMD’s Fusion.
This book is divided into three parts. The first part, which consists of chapters 1–10, focuses on exploring the OpenCL language and its capabilities. The second part, which consists of chapters 11–14, shows how OpenCL can be used to perform large-scale tasks commonly encountered in the field of high-performance computing. The last part, which consists of chapters 15 and 16, shows how OpenCL can be used to accelerate OpenGL applications.
The chapters of part 1 have been structured to serve the needs of a programmer who has never coded a line of OpenCL. Chapter 1 introduces the topic of OpenCL, explaining what it is, where it came from, and the basics of its operation. Chapters 2 and 3 explain how to code applications that run on the host, and chapters 4 and 5 show how to code kernels that run on compliant devices. Chapters 6 and 7 explore advanced topics that involve both host programming and kernel coding. Specifically, chapter 6 presents image processing and chapter 7 discusses the important topics of event processing and synchronization.
Chapters 8 and 9 discuss the concepts first presented in chapters 2 through 5, but using languages other than C. Chapter 8 discusses host/kernel coding in C++, and chapter 9 explains how to build OpenCL applications in Java and Python. If you aren’t obligated to program in C, I recommend that you use one of the toolsets discussed in these chapters.
Chapter 10 serves as a bridge between parts 1 and 2. It demonstrates how to take full advantage of OpenCL’s parallelism by implementing a simple reduction algorithm that adds together one million data points. It also presents helpful guidelines for coding practical OpenCL applications.
Chapters 11–14 get into the heavy-duty usage of OpenCL, where applications commonly operate on millions of data points. Chapter 11 discusses the implementation of MapReduce and two sorting algorithms: the bitonic sort and the radix sort. Chapter 12 covers operations on dense matrices, and chapter 13 explores operations on sparse matrices. Chapter 14 explains how OpenCL can be used to implement the fast Fourier transform (FFT).
Chapters 15 and 16 are my personal favorites. One of OpenCL’s great strengths is that it can be used to accelerate three-dimensional rendering, a topic of central interest in game development and scientific visualization. Chapter 15 introduces the topic of OpenCL-OpenGL interoperability and shows how the two toolsets can share data corresponding to vertex attributes. Chapter 16 expands on this and shows how OpenCL can accelerate OpenGL texture processing. These chapters require an understanding of OpenGL 3.3 and shader development, and both of these topics are explored in appendix B.
At the end of the book, the appendixes provide helpful information related to OpenCL, but the material isn’t directly used in common OpenCL development. Appendix A discusses the all-important topic of software development kits (SDKs), and explains how to install the SDKs provided by AMD and Nvidia. Appendix B discusses the basics of OpenGL and shader development. Appendix C explains how to install and use the Minimalist GNU for Windows (MinGW), which provides a GNU-like environment for building executables on the Windows operating system. Lastly, appendix D discusses the specification for embedded OpenCL.
In the end, it’s the code that matters. This book contains working code for over 60 OpenCL applications, and you can download the source code from the publisher’s website at www.manning.com/OpenCLinAction or www.manning.com/scarpino2/.
The download site provides a link pointing to an archive that contains code intended to be compiled with GNU-based build tools. This archive contains one folder for each chapter/appendix of the book, and each top-level folder has subfolders for example projects. For example, if you look in the Ch5/shuffle_test directory, you’ll find the source code for Chapter 5’s shuffle_test project.
As far as dependencies go, every project requires that the OpenCL library (OpenCL.lib on Windows, libOpenCL.so on *nix systems) be available on the development system. Appendix A discusses how to obtain this library by installing an appropriate software development kit (SDK).
In addition, chapters 6 and 16 discuss images, and the source code in these chapters makes use of the open-source PNG library. Chapter 6 explains how to obtain this library for different systems. Appendix B and chapters 15 and 16 all require access to OpenGL, and appendix B explains how to obtain and install this toolset.
As lazy as this may sound, I prefer to copy and paste working code into my applications rather than write code from scratch. This not only saves time, but also reduces the likelihood of producing bugs through typographical errors. All the code in this book is public domain, so you’re free to download and copy and paste portions of it into your applications. But before you do, it’s a good idea to understand the conventions I’ve used:
cl_platform_id structure is called platform, each cl_device_id structure is called device, each cl_context structure is called context, and so on.
main function calls on two functions: create_device returns a cl_device, and build_program creates and compiles a cl_program. Note that create_device searches for a GPU associated with the first available platform. If it can’t find a GPU, it searches for the first compliant CPU.
PROGRAM_FILE macro identifies the program file and KERNEL_FUNC identifies the kernel function.
AMDAPPSDKROOT on AMD platforms and CUDA on Nvidia platforms.
Nobody’s perfect. If I failed to convey my subject material clearly or (gasp) made a mistake, feel free to add a comment through Manning’s Author Online system. You can find the Author Online forum for this book by going to www.manning.com/OpenCLinAction and clicking the Author Online link.
Simple questions and concerns get rapid responses. In contrast, if you’re unhappy with line 402 of my bitonic sort implementation, it may take me some time to get back to you. I’m always happy to discuss general issues related to OpenCL, but if you’re looking for something complex and specific, such as help debugging a custom FFT, I will have to recommend that you find a professional consultant.
The figure on the cover of OpenCL in Action is captioned a “Kranjac,” or an inhabitant of the Carniola region in the Slovenian Alps. This illustration is taken from a recent reprint of Balthasar Hacquet’s Images and Descriptions of Southwestern and Eastern Wenda, Illyrians, and Slavs published by the Ethnographic Museum in Split, Croatia, in 2008. Hacquet (1739–1815) was an Austrian physician and scientist who spent many years studying the botany, geology, and ethnography of the Julian Alps, the mountain range that stretches from northeastern Italy to Slovenia and that is named after Julius Caesar. Hand drawn illustrations accompany the many scientific papers and books that Hacquet published.
The rich diversity of the drawings in Hacquet's publications speaks vividly of the uniqueness and individuality of the eastern Alpine regions just 200 years ago. This was a time when the dress codes of two villages separated by a few miles identified people uniquely as belonging to one or the other, and when members of a social class or trade could be easily distinguished by what they were wearing. Dress codes have changed since then and the diversity by region, so rich at the time, has faded away. It is now often hard to tell the inhabitant of one continent from another and today the inhabitants of the picturesque towns and villages in the Slovenian Alps are not readily distinguishable from the residents of other parts of Slovenia or the rest of Europe.
We at Manning celebrate the inventiveness, the initiative, and the fun of the computer business with book covers based on costumes from two centuries ago brought back to life by illustrations such as this one.