6

I have created following structure 'data' in C

typedef struct data
{
  double *dattr;                           
  int d_id;                                
  int bestCent;                            
}Data;

The 'dattr' is an array in above structure which is kept dynamic. Suppose I have to create 10 objects of above structure. i.e.

dataNode = (Data *)malloc (sizeof(Data) * 10);

and for every object of this structure I have to reallocate the memory in C for array 'dattr' using:

for(i=0; i<10; i++)
   dataNode[i].dattr = (double *)malloc(sizeof(double) * 3);

What should do to implement the same in OpenCL? How to allocate the memory for array 'dattr' once I allocate the memory for structure objects?

2 Answers 2

6

Memory allocation in OpenCL devices (for example, a GPU) must be performed in the host thread using clCreateBuffer (or clCreateImage2D/3D if you wish to use texture memory). These functions allow you automatically copy host data (created with malloc for example) to the device, but I usually prefer to explicitly use clEnqueueWriteBuffer/clEnqueueMapBuffer (or clEnqueueWriteImage/clEnqueueMapImage if using texture memory), so that I can profile the data transfers. Here's an example:

#define DATA_SIZE 1000

typedef struct data {
    cl_uint id;
    cl_uint x;
    cl_uint y;
} Data;

...

// Allocate data array in host
size_t dataSizeInBytes = DATA_SIZE * sizeof(Data);
DATA * dataArrayHost = (DATA *) malloc(dataSizeInBytes);

// Initialize data
...

// Create data array in device
cl_mem dataArrayDevice = clCreateBuffer(context, CL_MEM_READ_ONLY, dataSizeInBytes, NULL, &status );

// Copy data array to device
status = clEnqueueWriteBuffer(queue, dataArrayDevice, CL_TRUE, 0, dataSizeInBytes, &dataArrayHost, 0, NULL, NULL );

// Make sure to pass dataArrayDevice as kernel parameter
// Run kernel
...

What you need to consider is that you need to know the memory requirements of an OpenCL kernel before you execute it. As such memory allocation can be dynamic if performed before kernel execution (i.e. in host). Nothing stops you from calling the kernel several times, and in each of those times adjusting (allocating) the kernel memory requirements.

Having this into account, I advise you to rethink the way your approaching the problem. To begin, it is simpler (but not necessarily more efficient) to work with arrays of structures, than with structures of arrays (in which case, the arrays would have to have a fixed size anyway).

This is just to give you an idea of how OpenCL works. Take a look at Khronos OpenCL resource page, it has plenty of OpenCL tutorials and examples, and Khronos OpenCL page, which has the official OpenCL references, man pages and quick references cards.

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

3 Comments

I'll add that OpenCL isn't just some framework you slap on a finished product to make it work faster. You have to design your program's workflow on the OpenCL paradigm, not the other way around.
faken>> Thank you so much for your attention and reply to my question. But according to the requirement of the application I am designing I have to keep it dynamic. So I cannot have a fixed size array. Just wanted to check if there is any provision for above kind of memory allocation in opencl..Otherwise I have to rethink my approach as you have suggested.
what you need to consider is that you need to know the memory requirements of an opencl kernel before you execute it. As such memory allocation can be dynamic if performed before kernel execution (i.e. in host). Nothing stops you from calling the kernel several times, and in each of those times adjusting (allocating) the kernel memory requirements.
2

As suggested by Faken if you are concern with dynamic memory allocation and you are eager to change the algorithm a little bit, here is some hint:

The following code dynamically allocates local memory space and passes it as the 8th argument to the OpenCL kernel:

  int N; //Number_of_data_points, which will keep on changing as per your requirement  
   size_t localMemSize = ( N* sizeof(int));      
 ...   
 // Dynamically allocate local memory (allocated per workgroup)
 clSetKernelArg(kernel, 8, localMemSize, NULL);

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.