See also: CUDADevelopersGuide
Detection of OpenCL
If an application is built and linked against OpenCL then it is expected that it will run on a machine which has an OpenCL implementation installed. A typical application should create a GPU context on hosts containing an OpenCL-capable GPU and/or a CPU context on hosts with CPU-only support. The ATI Stream SDK can be used to provide a CPU-only implementation on Linux-hosts containing just an AMD or Intel CPU. The implementation will parallelize on a CPU context across the available processors. If an ATI OpenCL-compatible GPU is present, then the application can also request a GPU context and run on the GPU(s) (or GPU+CPU combination). On a machine containing an Nvidia GPU, the Nvidia OpenCL driver should be installed. Finally, on Mac OS X Snow Leopard, the OS itself provides an implementation which provides minimally a CPU context and also a GPU context for OpenCL-capable ATI or Nvidia GPUs.
The opencl_algorithms library contains an implementation of Dijkstra's Single Source Shortest Path algorithm (used by mris_pmake) and demonstrates how to write an algorithm which will run on CPU-only, GPU-only, CPU+GPU, or multi-GPU.
Changes to enable OpenCL during configuration ( configure.in )
This section gives an overview of how configure.in is changed and what stuff it exports. More often than not, one need not tamper with configure.in -- it is already changed to accommodate OpenCL.
* OpenCL support is enabled by using a --with-opencl=<path of cuda>. This should be the path to either the ATI Stream SDK or Nvidia OpenCL root. On Mac OS X, configure.in will automatically look in the appropriate Mac OS X Snow Leopard System directories for the headers and framework. The ./configure exports certain things which are helpful in compiling OpenCL programs ( and which are to be used in Makefile.am )
Flags which configure.in exports
These flags are typically used in the Makefile.am of any binary which has a CUDA replacement.
OPENCL_CFLAGS : This variable contains the include path of OpenCL header files. (eg. OPENCL_CFLAGS="-I<opencl_include_dir>" )
OPENCL_LIBS : This variable contains the OpenCL libraries to link against (eg. OPENCL_LIBS="-L<opencl_lib_dir> -lOpenCL" )
BUILDOPENCL : This important variable is exported as AM_CONDITIONAL. If configure finds OpenCL, it sets this flag and any Makefile.am can test this flag and if it exists, compile OpenCL specific stuff. This is illustrated in the next section.
FS_CUDA : This is defined and will be placed on config.h if OpenCL is found. Example usage would be:
#ifdef FS_OPENCL // We have implemented various flavors of the Dijkstra algorithm that runs // with OpenCL using either CPU-only, GPU+CPU, Multi GPU, or Multi GPU + CPU. // Based on what set of devices is available, this function will choose which // implementation to use. This version of Dijkstra selects which devices to use // automatically. // If compiled with OpenCL support, run the OpenCL version of the // algorithm runDijkstraOpenCL(&graph, &sourceVertices, results, 1); #else // If not compiled with OpenCL, run the reference version of the // algorithm runDijkstraRef(&graph, &sourceVertices, results, 1); #endif
Tweaking Makefile.am of the binary
Listing of Makefile.am of mris_pmake to illustrate how Makefile.am changes:
bin_PROGRAMS = mris_pmake mris_pmake_SOURCES = \ abs2rel.c \ asynch.cpp \ c_label.cpp \ C_mpmProg.cpp \ c_SMessage.cpp \ c_SSocket.cpp \ c_surface.cpp \ c_vertex.cpp \ dijkstra.cpp \ env.cpp \ general.cpp \ help.cpp \ mris_pmake.cpp \ rel2abs.c \ scanopt.cpp \ surface.cpp AM_CFLAGS=-I$(top_srcdir)/include AM_CXXFLAGS=-I$(top_srcdir)/include -I../opencl_algorithms/ mris_pmake_LDFLAGS = $(OS_LDFLAGS) if BUILDOPENCL # Include OpenCL version of algorithms mris_pmake_LDADD = $(addprefix $(top_builddir)/, $(LIBS_MGH)) ../opencl_algorithms/libopencl_algorithms.a $(OPENCL_LIBS) else # No OpenCL present mris_pmake_LDADD = $(addprefix $(top_builddir)/, $(LIBS_MGH)) ../opencl_algorithms/libopencl_algorithms.a endif EXTRA_DIST=asynch.h c_label.h C_mpmProg.h c_SMessage.h c_SSocket.h \ c_surface.h c_vertex.h dijkstra.h env.h general.h help.h pathconvert.h \ pstream.h scanopt.h surface.h # Our release target. Include files to be excluded here. They will be # found and removed after 'make install' is run during the 'make # release' target. EXCLUDE_FILES= include $(top_srcdir)/Makefile.extra
As one can notice, the Makefile.am of a OpenCL enabled code differs from normal Makefile.am only in the if BUILDOPENCL.. endif block.
OpenCL support is to be enclosed in if BUILDCUDA.. endif block ( which is exported by configure.in if it finds OpenCL)
- The only difference is the need to link against $(OPENCL_LIBS)
A lot of the code in oclCommon.cpp was derived from the NVIDIA GPU Computing SDK.