OpenCL™ with Code::Blocks tutorial
Les pages d'Alexandre

No logo

OpenCL™ is a great technology which allows to do parallelize multiple operations. Whereas Cuda only works on Nvidia graphics card, OpenCL™ works on both Nvidia and ATI graphics, and even other devices (such specific accelerated devices you will not find on Amazon). You may also know that AMD supports this technology, and most of the explanations you'll find about it comes from AMD.

OpenCL™ implementation is a set of C functions you will use, so that if you have the right compiler and drivers you will be able to develop applications for both Linux and Windows systems. If you are like me and don't want to develop platform specific applications, then you may not want to use IDE such as Visual Studio, but some like Code::Blocks instead. Why Code::Blocks ? Because it is widely used, it is light and it runs on Windows and Linux so that you can compile and test your application on each platform without having to change your habits.

Then as I spent a "few" time to find out how to use Code::Blocks with OpenCL™ (yes, I'm most a Java developer), I would like to save yours a bit explaining how to configure Code::Blocks for developing with OpenCL™ technology. Ready ? So let's start.

Before you start, are you sure you have an OpenCL™ compatible device in your computer ? If you are using a notebook, you may not have. If you're using a desktop, you may have (most of Nvidia and ATI graphics cards used nowadays are compatible).

First you will need to download :

You should install mingw before Code::Blocks as the second will look for the first on first startup so that it will simplify your work.

Is everything installed correctly ? Ok so open, without mystery, open Code::Blocks. If you don't know it, it will ask you for the defaut compiler to use and, if you installed mingw before, it will tell you it found. All is right.

Once it's open, click on "Settings" in the toolbar and click on "Compiler and debugger". Here you can configure several different compilers, it's useful for some people. Here, we will just create a new configuration to use it.

The selected compiler should be "GNU GCC Compiler", if not select if. Click on the "Copy" button and give the new configuration a name such as "OpenCL™ compiler" for example. Now you have a new configuration for the CNU GCC compiler that we will modify to compile our OpenCL™ programs.

Screen capture 1

In the configurations list, select the new one ("OpenCL™ compiler"). To enable OpenCL™ compilation will have to add only three elements :

Now you can create a new project which will use our customized compiler configuration as compiler and create a new main file in it and copy paste the following simple code. This sample just list the names and type the OpenCL™ compatible devices on your computer. AMD processor will be listed, I know for Intel ones.

#include <stdlib.h>
#include <CL/cl.h>

typedef struct DeviceDesc{
	cl_device_id    deviceId;
	cl_device_type  deviceType;
	char*           deviceTypeString;
	char*           deviceName;
} DeviceDesc;

int main(void)
{
	size_t              i;
	size_t              maxDevices = 5;
	cl_device_id*       deviceIDs = (cl_device_id*)malloc(maxDevices*sizeof(cl_device_id));
	cl_platform_id*     platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id));
	cl_int              err;
	cl_uint             num_entries = 1;
	cl_uint             available;
	cl_uint             numDevices;
	DeviceDesc*         devices;

	//Get available platforms (we will use the first result, I think most of the time we have 
	//one platform on personnal computers)
	cl_int result = clGetPlatformIDs(num_entries, platforms, &available);

	err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_ALL, maxDevices, deviceIDs, &numDevices);

	devices = (DeviceDesc*)malloc(numDevices*sizeof(DeviceDesc));

	for(i=0 ; i<numDevices ; i++)
	{
		devices[i].deviceId = deviceIDs[i];
		size_t actualSize;

		//Getting the device type (processor, graphics card, accelerator)
		result = clGetDeviceInfo(
			deviceIDs[i], 
			CL_DEVICE_TYPE, 
			sizeof(cl_device_type), 
			&devices[i].deviceType, 
			&actualSize);

		//Getting the human readable device type
		switch(devices[i].deviceType)
		{
			 case CL_DEVICE_TYPE_CPU:               
				devices[i].deviceTypeString = "Processor"; 
				break;
			 case CL_DEVICE_TYPE_GPU:               
				devices[i].deviceTypeString = "Graphics card"; 
				break;
			 case CL_DEVICE_TYPE_ACCELERATOR:       
				devices[i].deviceTypeString = "Accelerator"; 
				break;
			 default:                               
				devices[i].deviceTypeString = "NONE"; 
				break;
		}

		//Getting the device name
		size_t deviceNameLength = 4096;
		char* tempDeviceName = (char*)malloc(4096);
		result |= clGetDeviceInfo(
			deviceIDs[i], 
			CL_DEVICE_NAME, 
			deviceNameLength, 
			tempDeviceName, 
			&actualSize);
		if(result == CL_SUCCESS){
			devices[i].deviceName = (char*)malloc(actualSize);
			memcpy(devices[i].deviceName, tempDeviceName, actualSize);
			free(tempDeviceName);
		}

		//If an error occured
		if(result != CL_SUCCESS)
		{
			printf("Error while getting device info\n");
			return;
		}
	}

	//And finally we print the information we wanted to have
	for(i=0 ; i<numDevices ; i++){
		printf("Device %s is of type %s\n", devices[i].deviceName, devices[i].deviceTypeString);
	}

	//Free memory
	free(deviceIDs);
	free(platforms);
}
	

I wish this tutorial helped you a bit and will make you able you start your adventure with OpenCL™. This technology is really funny, and I wish I will find some time to work more on it.

Don't hesitate to contact me if you find an error or for another question. It will be a pleasure to share with you.

To continue with OpenCL programming, go to the second tutorial >>

Copyright © 2012 – Alexandre OBELLIANNE – Licence creative commons

Répondre
Nom *
Adresse mail (ne sera pas montrée) *
Site web
Message *
Envoyer