Setting up OpenCL using an Nvidia device on Ubuntu

In this post, I’m trying to figure out basics of OpenCL. In fact, this is not a tutorial about OpenCL, but about creating and building OpenCL applications on Ubuntu. The tutorial is actually describing my exploration around the libraries. I already have NVidia drivers installed, CUDA library and CUDA SDK installed on my machine.

An important thing for a library is to figure out the build process. Or, where are the various library parts and how to link them. SDK OpenCL demos have a complex master file to include in makefiles, located in NVIDIA_GPU_Computing_SDK/OpenCL/common/common_opencl.mk. This is a 274 lines makefile and, at the moment, I’m mostly interested in jumpstart the process.

So, let’s go to the OpenCL Vector Add sample (oclVectorAdd) and try to figure out what is going on there. A verbose build would help:

$ make verbose=1

mkdir -p ../../..//shared/lib/
mkdir -p obj/release
mkdir -p ../../..//OpenCL//bin//linux/release
g++ -W -Wall -Wimplicit -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function  -m64 -fno-strict-aliasing -I. -I../../..//OpenCL//common//inc -I../../..//shared//inc -DUNIX -O3  -o obj/release/oclVectorAdd.cpp.o -c oclVectorAdd.cpp
In file included from ../../..//OpenCL//common//inc/CL/opencl.h:44,
                 from ../../..//OpenCL//common//inc/oclUtils.h:26,
                 from oclVectorAdd.cpp:26:
../../..//OpenCL//common//inc/CL/cl_gl_ext.h:38: warning: "/*" within comment
oclVectorAdd.cpp: In function ‘int main(int, char**)’:
oclVectorAdd.cpp:163: warning: deprecated conversion from string constant to ‘char*’
oclVectorAdd.cpp:163: warning: unused variable ‘flags’
g++ -fPIC -m64 -o ../../..//OpenCL//bin//linux/release/oclVectorAdd obj/release/oclVectorAdd.cpp.o  -L/usr/lib64/ -L../../..//OpenCL//common//lib -L../../..//shared/lib/ -L../../..//shared//lib/linux  -lOpenCL  -L/usr/lib64/ -L../../..//OpenCL//common//lib -L../../..//shared/lib/ -L../../..//shared//lib/linux   -loclUtil_x86_64 -lshrutil_x86_64

So, we see three phases, one setting up directories, one compiling and one linking.

So, let’s split the compiling flags into groups – warning, optimization flags – and let’s define some include locations, and see if it works:

WARN_FLAGS="-W -Wall -Wimplicit -Wswitch -Wformat -Wchar-subscripts \
            -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith \
            -Wcast-align -Wreturn-type -Wno-unused-function"

OPT_FLAGS="-fno-strict-aliasing -O3"
INCLUDES="-I. -I../../..//OpenCL//common//inc -I../../..//shared//inc"
GCCFLAGS="${WARN_FLAGS} ${OPT_FLAGS} ${INCLUDES}"

And, compilation is simplified to:

$ g++ ${GCCFLAGS} -m64 -DUNIX -o obj/release/oclVectorAdd.cpp.o -c oclVectorAdd.cpp

Let’s do the same for the linking phase

LIBRARY_PATH="-L/usr/lib64/ -L../../..//OpenCL//common//lib \
              -L../../..//shared/lib/ -L../../..//shared//lib/linux \
              -L/usr/lib64/ -L../../..//OpenCL//common//lib \
              -L../../..//shared/lib/ -L../../..//shared//lib/linux"

LIB="-lOpenCL -loclUtil_x86_64 -lshrutil_x86_64"
LINKFLAGS="${LIBRARY_PATH} ${LIB}"

And linking now is:

$ g++ -fPIC -m64 \
          -o ../../..//OpenCL//bin//linux/release/oclVectorAdd  \
          obj/release/oclVectorAdd.cpp.o ${LINKFLAGS}

We need to relocate relative paths, but things have been greatly simplified. We don’t need to have LD_LIBRARY_PATH pointing to CUDA libraries. Running the program shows that things went smoothly.

$ ../../bin/linux/release/oclVectorAdd

We link to three libraries, OpenCL, oclUtil_x86_64 and shrutil_x86_64.

OpenCL obviously is OpenCL. It is located in /usr/lib64/libOpenCL.so in my installation.

The other library, oclUtil_x86_64, is a statically linked library provided by the SDK, located in NVIDIA_GPU_Computing_SDK/OpenCL/common/lib/liboclUtil_x86_64.a. This library has several goodies to simplify life with OpenCL. I am not sure if this library is to be used by developers, since a similar CUDA library make it clear that it shouldn’t be considered production code to be redistributed.

The third library, shrutil_x86_64, is located also in the SDK in /home/goulas/NVIDIA_GPU_Computing_SDK/shared/lib/libshrutil_x86_64.a. The name means shared utilities and is supposed to be used mostly for logging.

I suppose that I don’t need these SDK provided libraries, so I can continue with a lighter build process.

After all this exploration, I feel that this blog will have a contribution with a minimal OpenCL skeleton project, i.e. a Makefile and a Hello, OpenCL code.

A simple OpenCL program follows:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int err;
	cl_uint platforms;
	cl_platform_id platform = NULL;
	char cBuffer[1024];

	err = clGetPlatformIDs( 1, &platform, &platforms );
	if (err != CL_SUCCESS)
	{
		printf("Error in OpenCL call!\n");
		return EXIT_FAILURE;
	}
	printf("Number of platforms: %d\n", platforms);

	err = clGetPlatformInfo( platform, CL_PLATFORM_NAME, sizeof(cBuffer), cBuffer, NULL );
	if (err != CL_SUCCESS)
	{
		printf("Error in OpenCL call!\n");
		return EXIT_FAILURE;
	}
	printf("CL_PLATFORM_NAME :\t %s\n", cBuffer);

	err = clGetPlatformInfo( platform, CL_PLATFORM_VERSION,     sizeof(cBuffer), cBuffer, NULL );
	if (err != CL_SUCCESS)
	{
		printf("Error in OpenCL call!\n");
		return EXIT_FAILURE;
	}
	printf("CL_PLATFORM_VERSION :\t %s\n", cBuffer);
}

And, based on the above discussion, the Makefile:

TARGET	:= oclHello
OBJ	:= oclHello.o

WARN_FLAGS 	:= -W -Wall -Wimplicit -Wswitch -Wformat -Wchar-subscripts \
		-Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith \
		-Wcast-align -Wreturn-type -Wno-unused-function
OPT_FLAGS	:= -fno-strict-aliasing -O3
INCLUDES	:= -I/usr/local/cuda/include
LIBRARY_PATH	:= -L/usr/lib64/
LIB		:= -lOpenCL
CXXFLAGS	:= -m64 -DUNIX $(WARN_FLAGS) $(OPT_FLAGS) $(INCLUDES)
LDFLAGS		:= $(LIBRARY_PATH) $(LIB)

.PHONY:		clean

$(TARGET):	$(OBJ)
	g++ -fPIC -m64 -o $@ $(OBJ) $(LDFLAGS)

clean:
	$(RM) $(TARGET) $(OBJ)

Running the above on my Ubuntu gives:

$ ./oclHello
Number of platforms: 1
CL_PLATFORM_NAME :	 NVIDIA CUDA
CL_PLATFORM_VERSION :	 OpenCL 1.0 CUDA 4.0.1
Advertisements

Posted on October 28, 2011, in Programming and tagged . Bookmark the permalink. 2 Comments.

  1. Hi

    Thanks for the post. I helped me to kick-off with OpenCL. I think you also need to include to include the header file file related to opencl as follows:

    // All OpenCL headers
    #if defined (__APPLE__) || defined(MACOSX)
        #include &lt;OpenCL/opencl.h&gt;
    #else
        #include &lt;CL/opencl.h&gt;
    #endif 
    

    Regards
    Sajjad

  1. Pingback: Linux Mint 15 and OpenCL (nvidia) | AranHase Archives

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: