从指针计算数组索引

时间:2009-09-20 19:03:06

标签: c++ pointers cuda opencl

我和一些同行正在开发游戏(Rigs ofRods)并且正在尝试将OpenCL集成到物理计算中。与此同时,我们正在尝试对数据结构进行一些非常需要的清理。我想我应该说我们正在尝试清理我们的数据结构并注意OpenCL的要求。

使用开放CL的一个问题是无法使用指针,因为内存空间不同。从我对OpenCL的了解很少,将所有数据复制到GPU上然后执行计算,指针值将被复制,但地址不会与预期的地址相对应。

有问题的数据集中在一个数组中,当对象需要该数据时,它们使用指向所需对象的指针,或存储数组索引。

考虑OpenCL的一个解决方案是使用数组索引而不是指针。这导致硬耦合,可能导致后来的头痛。作为一种解决方案,我有想法根据起始地址和当前地址计算数组索引。这当然只适用于连续数组。

我写了一个示例应用程序来测试它并且它运行得很好,有些人也在不同的平台上验证它。

#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;
}

我担心这更像是一个kuredge而不是一个bonified解决方案。我知道这不会产生非连续的记忆。

基本上我的问题是这样的:
在已知的连续记忆中使用这种方法会有什么陷阱? 你怎么能说它是连续的?
人们在处理此类问题时使用了哪些方法?

谢谢,如果关闭格式化我的意见,这是我第一次发布问题。

3 个答案:

答案 0 :(得分:12)

这应该为您提供pointer相对于base的索引:

pointer - base

是的,就这么简单。 =]

使用ptrdiff_t可移植地存储结果。

答案 1 :(得分:3)

尽管指针的简单减法有效,但建议使用std::distance。这也适用于非指针的迭代器类型,也可以为自定义类型重载。对于指针,结果将是ptrdiff_t

答案 2 :(得分:1)

#define ARRAY_INDEX_FROM_ADDR(base, addr, type) \
(((uintptr_t)(addr)-(uintptr_t)(base))/sizeof(type))

如果不使用C99,请使用unsigned long long代替uintptr_t