2014-12-05 137 views
0

我遇到這行代碼的一些問題:__local結構陣列的OpenCL

__local cl_var new_vars[10]; 

這些所有的工作:

__local cl_var test; 
__local int test[10]; 
__local cl_var * test 

參考,cl_var是:

typedef struct cl_var{ 
    int var; 
    struct cl_var* next; 
} cl_var; 

試圖編譯時遇到seg錯誤。我使用JOCL包,不知道這是否有所作爲。

爲什麼我不能有一個本地聲明的結構數組的任何理由?

(我試圖改變結構定義,包括在不同的地方本地)

+1

我不認爲你可以包含一個指向自己的指針。由於它尚未定義。此外,它正在生成無限遞歸問題。 – DarkZeros 2014-12-05 10:23:26

+0

@DarkZeros我最初確實有這個問題,但包括struct關鍵字固定,我猜它是一個不同的命名空間。此外,它在任何地方都可以,除非將它用作本地數組。 – 2014-12-05 10:48:06

+0

'我在編譯時遇到seg錯誤。'你的意思是你在編譯時**得到一個段錯誤**? – 2014-12-05 10:48:48

回答

0

的原因是內存對齊。根據article和其中的評論,您必須小心對齊。 David Garcia在這個頁面的註釋部分中的解釋非常明確:一些編譯器可以選擇填充16個字節的結構大小。

有一個在此post in Khronos forum重要的附加信息:在OpenCL的

基本數據類型(整數和浮點數據類型)具有限定的尺寸和對準要求(參考的OpenCL 1.1規範的6.1.5節) 。要確保在設備上使用這些數據類型的主機&之間的對齊匹配,請使用cl_來聲明將由主機和設備共享的結構(請參閱1.1規範中的表6.1之後的表)。

所以,你應該用cl_float代替float,也許還可以指定明確的定位,如果我理解spec page on basic OpenCL types

對於三分量矢量數據類型,數據類型的大小4 * sizeof(組件)。這意味着3分量矢量數據類型將與4 * sizeof(分量)邊界對齊。

所以也許明確的對齊將解決您的問題。

除此之外,這個答案的第二部分:

請注意,這僅適用於整數&浮點數據類型。對齊規則不適用於指針。這是指針不能被嵌入到OpenCL結構中的一個原因。

OpenCL的規範是在這個問題上明確表示:「你不能將包含指針到OpenCL的一個結構」(從here報價,並且也證實there,我懶得搶規範網頁.. 。:))。顯然這裏並不是這種情況,但是你的結構將不會成爲內核參數的有效類型。

+0

我不把它傳遞給內核參數,這些都是在函數中聲明的,也是 - 它導致問題的唯一時間是在本地數組內使用時,以任何其他描述它的方式使用。 – 2014-12-05 10:49:13

+0

是的,這就是爲什麼結構體中的指針並不真正相關,但我認爲很好的提及。但是你有沒有試圖聲明一個16字節的結構對齊? – Bentoy13 2014-12-05 13:15:10

+0

我沒有,我會考慮現在這樣做,但爲什麼只會影響本地數組,沒有任何其他類型的數組,或本地指針,或本地正常? – 2014-12-05 19:46:10

0

我無法在編譯時(甚至是運行時)重現錯誤。我不熟悉JOCL,因此無法在這方面提供幫助。 我正在使用Windows,NVIDIA和JIT編譯OpenCL內核。

您是否還在內核中使用分配的內存?new_vars或者您是否只聲明__local cl_var new_vars[10];並且發生錯誤?

另外你是什麼意思與「我試圖改變結構定義包括本地在不同的地方」?您是否已將local地址空間限定符添加到「下一個」指針? 如果是這樣,那麼我的以下解釋可能不是解決方案。

從我所看到的,錯誤的潛在原因是缺少地址空間限定符(無法驗證,因爲我無法重現錯誤)。您的問題是OpenCL中的指針類型始終帶有地址空間限定符private,local,globalconstant(請參閱here)。如果將它保留,OpenCL默認選擇private:「如果未指定地址空間限定符,則聲明爲指針的變量被視爲指向__私有地址空間」(請參閱​​Notes)。

這就是你的結構發生了什麼。在struct中聲明瞭一個指向結構本身的指針,但是你沒有指定任何地址空間限定符,所以private被默認設置。

寫作

typedef struct cl_var{ 
    int var; 
    struct cl_var* next; 
} cl_var; 

相當於寫

typedef struct cl_var{ 
    int var; 
    private struct cl_var* next; 
} cl_var; 

當寫__local cl_var new_vars[10];靜態分配在本地內存10個cl_var對象,地址空間限定符不匹配,因爲對象駐留在本地內存,但期望在私有內存中指向一個對象(「下一個」)。因此,在對象中使用指針時,程序應該會崩潰,但只能在運行時而不是編譯時(除非編譯器非常敏感 - 在這種情況下實際上是一件好事)。

通過編寫

typedef struct cl_var{ 
    int var; 
    local struct cl_var* next; 
} cl_var; 

你應該能夠分配內存。注意:儘量避免使用「新」來命名你的數組,因爲它與動態內存分配的聯繫(並且動態內存分配不在你的示例代碼中發生的事情),它可能會讓人困惑。