1

There are lots of questions about how to read an array from the device, but I only wanna read a single float value from the device. Or can it only read an array from the device?

I create a buffer for (float) sum like below.

ocl.sum = clCreateBuffer(context, CL_MEM_READ_WRITE, 1, NULL, &err);

Set the arg like this.

clSetKernelArg(kernel, 0, sizeof(cl_mem), &ocl.arr);
clSetKernelArg(kernel, 1, sizeof(cl_float), &ocl.sum);

In the kernel, I calculate the sum.

kernel calculate(global arr, float sum)
{
...
sum = 100.0f;
}

How can I get the sum from the device?

float result = 0.f;
err = clEnqueueReadBuffer(queue, ocl.sum, CL_TRUE, 0, 1, &result, 0, NULL, NULL);

print(result);
Lemons
  • 379
  • 4
  • 14
LinNotFound
  • 531
  • 1
  • 5
  • 12
  • 1
    I wanna do a reduction in the kernel as well, like [this] (https://stackoverflow.com/questions/20613013/opencl-float-sum-reduction/55423883#55423883) question. But instead of passing a group sums[], I think passing a single value is higher performance. Isn't it? Is it possible? – LinNotFound Mar 29 '19 at 18:56

1 Answers1

2

Reading from the device, whether that is for a single value or an array have to go via global memory. So the kernel signature has to be of kernel calculate(..., global float *sum). Then you read it from the device the way you posted - by passing &result to clEnqueueReadBuffer.

doqtor
  • 8,414
  • 2
  • 20
  • 36
  • Thanks for your answer! I just tried your solution now. I'm sorry I'm new to C as well, so not sure where I did wrong. I changed `kernel calculate(..., float sum)` to `kernel calculate(..., global float *sum)` as your suggestion. And I did `float x; *sum += x; ` in kernel function. Then I got the error that `OpenCL error during 'setting arg 2' `. I set arg like this `clSetKernelArg(kernel, 1, sizeof(cl_float), &ocl.sum);` , anything wrong? – LinNotFound Mar 29 '19 at 12:49
  • I defined `sum` as `cl_mem` and create its buffer as `1`, is that right? I only get `0.0000E+00` return.. – LinNotFound Mar 29 '19 at 18:34
  • @LinFeng For buffer arguments, you must set the size argument in the `clSetKernelArg` call to the `sizeof` the memory object, i.e. `sizeof(ocl.sum)`, not the length of the buffer. I'm not sure what you mean by "create its buffer as 1" but if you mean the size in bytes specified when creating the buffer, you will need to use `sizeof(cl_float)` as the buffer only cares about *bytes*. – pmdj Mar 30 '19 at 09:32
  • @pmdj I got it now. Thank you very much! – LinNotFound Mar 30 '19 at 17:26