views:

389

answers:

2

Me and some peers are working on a game (Rigs ofRods) and are trying to integrate OpenCL for physics calculation. At the same time we are trying to do some much needed cleanup of our data structures. I guess I should say we are trying to cleanup our data structures and be mindful of OpenCL requirements.

One of the problems with using open CL is the inability to use pointers as the memory space is different. From what little I know of OpenCL is copies all the data onto the GPU then performs the calculations, pointer values would be copied but the address would not correspond to the expected address.

The data in question is centralized in an array, when objects need to that data they use pointers to the object it needs, or stores an array index.

One solution to account for OpenCL is to use array index instead of pointers. This leads to hard coupling that could lead to headaches later on. As a solution I had the idea of calculating the array index based on the address of the start and the address of the current. This of course would only work with a continuous array.

I wrote a sample app to test this and it worked just fine, some people verified it on different platforms as well.

#include <iostream>

typedef struct beam_t
{
 unsigned int item;
} beam_t;

#define GLOBAL_STATIC_ASSERT(expr, msg)   \
  extern char STATIC_ASSERTION__##msg[1]; \
  extern char STATIC_ASSERTION__##msg[(expr)?1:2]


#ifdef __amd64
typedef unsigned long pointer_int;
#else
typedef unsigned int pointer_int;
#endif
GLOBAL_STATIC_ASSERT(sizeof(pointer_int) == sizeof(pointer_int*), integer_size);
#define MAX_BEAM 5


int main ()
{
 beam_t beams[MAX_BEAM];
 beam_t* beam_start = &beams[0];
 beam_t* beam_ptr = NULL;

 std::cout << "beams: " << &beams << "\n";

 for( pointer_int i = 0; i < MAX_BEAM; ++i )
 {
  beam_ptr = &beams[i];
  pointer_int diff = ((pointer_int)beam_ptr - (pointer_int)beam_start);
  std::cout << "beams[" << i << "]: " << beam_ptr
      << "\t calculated index:" <<  diff / sizeof(beam_t)
      << "\n";
 }
 return 0;
}

I'm concerned that this more of a kludge than a bonified solution. I'm aware that this would not work no non-coninuous memory.

basically my questions are this:
What would be the pitfalls for using this approach in known coninuous memory?
How would you be able to tell it was continuous?
What approaches have people used when dealing with this type of issue?

Thanks, and my appologies if the formating is off, this is my first time posting a question.

+7  A: 

This should give you the index of pointer relative to base:

pointer - base

Yes, it's that easy. =]

Use ptrdiff_t to store the result portably.

strager
yes I figured that out, I did not know about the ptrdiff_t though, seams like that would replace the pointer_int type I typedef'd in my example.I was more wondering about reliability and coding practices. ie Is this is _good_ approach as opposed to a hack/kludge that works.
Apeiron
It's the idiomatic approach. In C and C++, POD arrays are guaranteed to be contiguous. I would expect the same to be true in CUDA and OpenCL.
greyfade
Not just POD, *all* arrays are guaranteed to be contiguous.
jalf
+1  A: 

Although simple subtraction of pointers works, it's advisable to use std::distance. This will also work for iterator types that aren't pointers, and can be overloaded for custom types, too. The result, for pointers, will be a ptrdiff_t.

xtofl
I didn't know about `std::distance`. Seems useful. However, isn't `operator-` overloaded for STL iterator types?
strager