2009-09-20 86 views
2

我和一些同齡人正在研究遊戲(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; 
} 

我擔心的是,這不僅僅是一個優化的解決方案。我知道這不會有任何非連續的記憶。

基本上我的問題是這樣的:
在已知的連續記憶中使用這種方法會有什麼缺陷?
你會如何判斷它是連續的?
人們在處理這類問題時使用了什麼方法?

謝謝,以及我的appologies如果格式化關閉,這是我第一次發佈一個問題。

回答

12

這應該給你pointer相對的指數base

pointer - base 

是的,就是這麼簡單。 =]

使用ptrdiff_t可移植地存儲結果。

+0

是的,我想通了這一點,我不知道該ptrdiff_t的,雖然,這樣的接縫將取代pointer_int類型我在我的例子typedef定義。 我更想知道可靠性和編碼實踐。這是否是一種好方法,而不是一種有效的黑客/混合物。 – Apeiron 2009-09-20 19:22:28

+1

這是慣用的方法。在C和C++中,POD數組保證是連續的。我希望CUDA和OpenCL也是如此。 – greyfade 2009-09-20 19:46:02

+0

不僅POD,*所有*數組都保證是連續的。 – jalf 2009-09-20 20:35:26

3

雖然指針的簡單減法有效,但建議使用std::distance。這也適用於不是指針的迭代器類型,也可以爲自定義類型重載。對於指針,結果將是ptrdiff_t

+1

我不知道'std :: distance'。看起來很有用。但是,STL迭代器類型不是'operator-'重載嗎? – strager 2009-09-20 20:45:35

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

如果不使用C99,使用uintptr_tunsigned long long代替