4

I am new to openCL and I am trying to start out with a very simple kernel. Right now I am just trying to get data transferred to the kernel and back so I can verify the correct data is being set. However, I am getting very weird behavior. Here is my host code:

string PROGRAM_FILE = "C:\\Projects\\AnimatLabSDK\\OpenNeuronCL\\Libraries\\OpenNeuronCL\\Kernels\\FastSpikingNeuron.cl";
string KERNEL_FUNC = "FastSpikingNeuron";

std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;  
int i;

// Data
cl::NDRange ndGlobal(DATA_SIZE);  
cl::NDRange ndLocal(LOCAL_SIZE);

cl_float aryVmIn[DATA_SIZE], aryVmOut[DATA_SIZE];
cl_float aryVahp[DATA_SIZE], aryTestOut[DATA_SIZE];

try {
  // Initialize data
  for(i=0; i<DATA_SIZE; i++) {
     aryVmIn[i] = i*0.1f; //0.0f;
     aryVahp[i] = i*0.1f; //0.0f;
  }

  // Place the GPU devices of the first platform into a context
  cl::Platform::get(&platforms);
  platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
  cl::Context context(devices);

  // Create kernel
  std::ifstream programFile(PROGRAM_FILE);
  std::string programString(std::istreambuf_iterator<char>(programFile),
        (std::istreambuf_iterator<char>()));
  cl::Program::Sources source(1, std::make_pair(programString.c_str(),
        programString.length()+1));
  cl::Program program(context, source);

  //std::cout << "Program kernel: " << std::endl << programString << std::endl;

  try
  {
    program.build(devices);
  }
  catch(cl::Error e)
  {
      std::cout << e.what() << ": Error code " << e.err() << std::endl;   
      string buildlog;
      program.getBuildInfo( devices[0], (cl_program_build_info)CL_PROGRAM_BUILD_LOG, &buildlog );
      std::cout << "Error: " << buildlog << std::endl;   
      throw e;
  }

  cl::Kernel kernel(program, KERNEL_FUNC.c_str());

  // Create buffers
  cl::Buffer bufferVmIn(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(aryVmIn), aryVmIn);
  cl::Buffer bufferVmOut(context, CL_MEM_WRITE_ONLY, sizeof(aryVmOut), NULL);
  cl::Buffer bufferVahp(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(aryVahp), aryVahp);
  cl::Buffer bufferTestOut(context, CL_MEM_WRITE_ONLY, sizeof(aryTestOut), NULL);

  // Set kernel arguments
  kernel.setArg(0, bufferVmIn);
  kernel.setArg(1, bufferVmOut);
  kernel.setArg(2, bufferVahp);
  kernel.setArg(3, bufferTestOut);

  // Create queue and enqueue kernel-execution command
  cl::CommandQueue queue(context, devices[0]);

  queue.enqueueWriteBuffer(bufferVmIn, CL_TRUE, 0, sizeof(aryVmIn),  aryVmIn, NULL, NULL);
  queue.enqueueWriteBuffer(bufferVahp, CL_TRUE, 0, sizeof(aryVahp),  aryVahp, NULL, NULL);

  queue.enqueueNDRangeKernel(kernel, NULL, ndGlobal, ndLocal);

  queue.enqueueReadBuffer(bufferVmOut, CL_TRUE, 0, sizeof(aryVmOut),  aryVmOut, NULL, NULL);
  queue.enqueueReadBuffer(bufferTestOut, CL_TRUE, 0, sizeof(aryTestOut),  aryTestOut, NULL, NULL);

  // Display updated buffer
  for(i=0; i<10; i++) 
  {
      printf("%6.5f, %6.5f", aryVmOut[i], aryTestOut[i]);
      printf("\n");
  }  
}
catch(cl::Error e) 
{
  std::cout << e.what() << ": Error code " << e.err() << std::endl;   
}

And here is my kernel:

__kernel void FastSpikingNeuron(__global float *aryVmIn, __global float *aryVmOut, __global float *aryVahp, __global float *aryTestOut)
{
int gid = get_global_id(0);
local float fltVahp;

fltVahp = aryVahp[gid];

aryVmOut[gid] = fltVahp;
aryTestOut[gid] = fltVahp;
}

I am simply setting some data and then trying to read out Vmout and TestOut and then view some of their contents. When I run this application I get the following output:

0.00000, 0.90000
0.10000, 0.90000
0.20000, 0.90000
0.30000, 0.90000
0.40000, 0.90000
0.50000, 0.90000
0.60000, 0.90000
0.70000, 0.90000
0.80000, 0.90000
0.90000, 0.90000

This is not making any sense to me so far. In the kernel I am setting both VmOut and TestOut to be the exact same variable, yet when I read it back to the host I get different results. I am doing something wrong here, but I have not yet been able to figure out what it is. Any help from someone more experienced in opencl would be much appreciated.

Thanks David

1
  • What happens if you swap the last two lines of the kernel? Commented Nov 25, 2012 at 5:51

1 Answer 1

3

You have a race condition in your kernel, caused by having multiple work items storing different values to the same memory location, which is why you're getting strange results.

Reminder - the definition of local address space is:

The __local or local address space name is used to describe variables that need to be allocated in local memory and are shared by all work-items of a work-group.

If you want a different value for each work item, just omit the local modifier.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.