This is source code for the host. init and checkErr (with getErrorDesc) are very useful functions. Check the Home page for an overview and other code.

Download / Views Formatted Source code: http://opencltutorial2.codeplex.com/SourceControl/changeset/view/366cecf0eb3d#init.cpp

#include <utility>
#define __NO_STD_VECTOR
#include <CL/cl.hpp>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <iterator>
#include <time.h>

#define CONTEXT_GPU 1
#define CONTEXT_CPU 2

#define MY_WORKSIZE 120

void makeContext(cl::Context* _context, const unsigned char type = CONTEXT_GPU);
void makeProgram(const cl::Context* _context, cl::vector<cl::Device>* _devices, const char* filename, cl::Program* program);
void init(cl::Context* _context, cl::vector<cl::Device>* _devices, const char* filename, cl::Program* program);

float raw_data[MY_WORKSIZE];
float result_data[MY_WORKSIZE];

const char* getErrorDesc(int err);

inline void checkErr(cl_int err, const char * name)
{
if (err != CL_SUCCESS) {
std::cerr << "ERROR: " << name
<< " (" << err << "). Output: " << getErrorDesc(err) << std::endl;
exit(EXIT_FAILURE);
}
}


int main()
{

//Init Testing data
unsigned int cnt;

for(cnt = 0; cnt < MY_WORKSIZE; cnt++)
{
raw_data[cnt] = cnt;
}


for(cnt = 0; cnt < MY_WORKSIZE; cnt++)
{
result_data[cnt] = 444;
}



//open cl device / management stuff
cl::Context context; //a collection of open cl memory regions, devices and program
cl::Program program; //a collection of functions which can be runned on hardware
cl::vector<cl::Device> devices; //a number of hardware where our functions can be executed on

//DEBUG
cl_int errorlevel;

//init open cl. Get the gpu and compile double_number.cl so we can start it later on it.
//the double_number program must be started later explicitly
init(&context, &devices, "double_number.cl", &program);

//selecting the desired function(s) of the program to run on the hardware e.g. doubleNumbers() out of math.cl
cl::Kernel kernel(program, "hello", &errorlevel);
checkErr(errorlevel, "Kernel::Kernel()");

//create Buffers for input / output for the hardware
cl::Buffer inputBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, MY_WORKSIZE*sizeof(float), raw_data, &errorlevel);
checkErr(errorlevel, "Buffer::Buffer() input");
cl::Buffer outputBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, MY_WORKSIZE*sizeof(float), result_data, &errorlevel);
checkErr(errorlevel, "Buffer::Buffer() output");

//tell our function the address of the buffers like void doubleNumbers(int* input, int* output)
errorlevel = kernel.setArg(0, inputBuffer);
checkErr(errorlevel, "Kernel::setArg() input");

errorlevel = kernel.setArg(1, outputBuffer);
checkErr(errorlevel, "Kernel::setArg() output");

//create an execute-queue for the device(s), a must have in open cl
cl::CommandQueue queue(context, devices[0], 0, &errorlevel);
checkErr(errorlevel, "CommandQueue::CommandQueue()");

//create an event where the progress of the executeable is logged
cl::Event event;

//put our function into the execute-queue
errorlevel = queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(MY_WORKSIZE*sizeof(float)), cl::NDRange(1, 1), NULL, &event);
checkErr(errorlevel, "CommandQueue::enqueueNDRangeKernel()");

//wait until the executeable is finished
event.wait();

//read the data from the hardware back to our cpu memory
errorlevel = queue.enqueueReadBuffer(outputBuffer, CL_TRUE, 0, MY_WORKSIZE*sizeof(float), result_data);
checkErr(errorlevel, "CommandQueue::enqueueReadBuffer()");

//Output Testing data
for(cnt = 0; cnt < MY_WORKSIZE; cnt++)
{
std::cout << "Element " << cnt << ": " << result_data[cnt] << std::endl;
}

return(0);
}


void init(cl::Context* _context, cl::vector<cl::Device>* _devices, const char* filename, cl::Program* _program)
{
//setup stuff
makeContext(_context, CONTEXT_GPU);

*_devices = _context->getInfo<CL_CONTEXT_DEVICES>();
checkErr(_devices->size() > 0 ? CL_SUCCESS : -1, "devices.size() > 0");

makeProgram(_context, _devices, filename, _program);

}

void makeProgram(const cl::Context* _context, cl::vector<cl::Device>* _devices, const char* filename, cl::Program* program)
{
cl_int errorlevel;
std::ifstream file(filename);
checkErr(file.is_open() ? CL_SUCCESS:-1, filename);

std::string prog(std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>()));

cl::Program::Sources source(1, std::make_pair(prog.c_str(), prog.length()+1));
*(program) = cl::Program(*_context, source);
errorlevel = program->build(*_devices,"");

cl::STRING_CLASS buildLog;
program->getBuildInfo((*_devices)[0], CL_PROGRAM_BUILD_LOG, &buildLog);
std::cout << "Build Log: \n" << buildLog.c_str() << std::endl;
}

void makeContext(cl::Context* _context, const unsigned char type)
{
cl_int errorlevel;
cl::vector <cl::Platform> platformVector;
cl::Platform::get(&platformVector);
checkErr(platformVector.size()!=0 ? CL_SUCCESS : -1, "cl::Platform::get");


std::string platformVendor;

cl_context_properties cprops[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platformVector[0])(), 0};

*(_context) = cl::Context(CL_DEVICE_TYPE_GPU, cprops, NULL, NULL, &errorlevel);
checkErr(errorlevel, "Conext::Context()");

}

const char* getErrorDesc(int err)
{
switch (err)
{
case CL_SUCCESS: return "";
case CL_DEVICE_NOT_FOUND : return "CL_DEVICE_NOT_FOUND";
case CL_COMPILER_NOT_AVAILABLE : return "CL_COMPILER_NOT_AVAILABLE";
case CL_MEM_OBJECT_ALLOCATION_FAILURE : return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
case CL_OUT_OF_RESOURCES : return "CL_OUT_OF_RESOURCES";
case CL_OUT_OF_HOST_MEMORY : return "CL_OUT_OF_HOST_MEMORY";
case CL_PROFILING_INFO_NOT_AVAILABLE : return "CL_PROFILING_INFO_NOT_AVAILABLE";
case CL_MEM_COPY_OVERLAP : return "CL_MEM_COPY_OVERLAP";
case CL_IMAGE_FORMAT_MISMATCH : return "CL_IMAGE_FORMAT_MISMATCH";
case CL_IMAGE_FORMAT_NOT_SUPPORTED : return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
case CL_BUILD_PROGRAM_FAILURE : return "CL_BUILD_PROGRAM_FAILURE";
case CL_MAP_FAILURE : return "CL_MAP_FAILURE";

case CL_INVALID_VALUE : return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE_TYPE : return "CL_INVALID_DEVICE_TYPE";
case CL_INVALID_PLATFORM : return "CL_INVALID_PLATFORM";
case CL_INVALID_DEVICE : return "CL_INVALID_DEVICE";
case CL_INVALID_CONTEXT : return "CL_INVALID_CONTEXT";
case CL_INVALID_QUEUE_PROPERTIES : return "CL_INVALID_QUEUE_PROPERTIES";
case CL_INVALID_COMMAND_QUEUE : return "CL_INVALID_COMMAND_QUEUE";
case CL_INVALID_HOST_PTR : return "CL_INVALID_HOST_PTR";
case CL_INVALID_MEM_OBJECT : return "CL_INVALID_MEM_OBJECT";
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
case CL_INVALID_IMAGE_SIZE : return "CL_INVALID_IMAGE_SIZE";
case CL_INVALID_SAMPLER : return "CL_INVALID_SAMPLER";
case CL_INVALID_BINARY : return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS : return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_PROGRAM : return "CL_INVALID_PROGRAM";
case CL_INVALID_PROGRAM_EXECUTABLE : return "CL_INVALID_PROGRAM_EXECUTABLE";
case CL_INVALID_KERNEL_NAME : return "CL_INVALID_KERNEL_NAME";
case CL_INVALID_KERNEL_DEFINITION : return "CL_INVALID_KERNEL_DEFINITION";
case CL_INVALID_KERNEL : return "CL_INVALID_KERNEL";
case CL_INVALID_ARG_INDEX : return "CL_INVALID_ARG_INDEX";
case CL_INVALID_ARG_VALUE : return "CL_INVALID_ARG_VALUE";
case CL_INVALID_ARG_SIZE : return "CL_INVALID_ARG_SIZE";
case CL_INVALID_KERNEL_ARGS : return "CL_INVALID_KERNEL_ARGS";
case CL_INVALID_WORK_DIMENSION : return "CL_INVALID_WORK_DIMENSION";
case CL_INVALID_WORK_GROUP_SIZE : return "CL_INVALID_WORK_GROUP_SIZE";
case CL_INVALID_WORK_ITEM_SIZE : return "CL_INVALID_WORK_ITEM_SIZE";
case CL_INVALID_GLOBAL_OFFSET : return "CL_INVALID_GLOBAL_OFFSET";
case CL_INVALID_EVENT_WAIT_LIST : return "CL_INVALID_EVENT_WAIT_LIST";
case CL_INVALID_OPERATION : return "CL_INVALID_OPERATION";
case CL_INVALID_GL_OBJECT : return "CL_INVALID_GL_OBJECT";
case CL_INVALID_BUFFER_SIZE : return "CL_INVALID_BUFFER_SIZE";
case CL_INVALID_MIP_LEVEL : return "CL_INVALID_MIP_LEVEL";
default: return "Unknown Error";
}
}

Last edited May 6, 2012 at 1:15 AM by rohezal, version 3

Comments

No comments yet.