2017-06-03 70 views
3

我有一個關於在Intel CPU上使用OpenCL中的結構的問題。我目前的內核訪問下列方式使用結構兩個緩衝區:Intel OpenCL編譯器:優化結構使用

struct pair { 
    float first; 
    float second; 
}; 

inline const float f(const struct pair param) { 
    return param.first * param.second; 
} 

inline const struct pair access_func(__global float const * const a, __global float const * const b, const int i) { 
    struct pair res = { 
      a[i], 
      b[i] 
    }; 
    return res; 
} 

// slow 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = f(access_func(a, b, i)); 

// ... 
} 

當我改變以下列方式內核運行速度更快:

// fast 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = a[i] * b[ i ]; 

// ... 
} 

有沒有辦法讓英特爾編譯器做這個優化? NVIDIA編譯器似乎能夠做到這一點,因爲我沒有看到GPU上運行時間的差異。

提前致謝!

+0

難道它是一切都是一個常量,並高度重視緩存管理? –

+0

我嘗試刪除'const'關鍵字,但這並沒有解決問題。 –

回答

0

考慮到OpenCL設備和主機之間和/或OpenCL設備上的多個內核之間共享緩衝區,編譯器無法對數據的內存佈局進行優化;最有效的佈局將取決於內核中的訪問模式,並且對於每個內核來說,這些顯然會有所不同。

您需要明智地選擇數據的內存佈局;這是GPU編程中最難的部分之一。請參閱OpenCL優化指南,瞭解您選擇的每個實施方案,以瞭解他們的偏好。有時,通過從內存複製local內存,然後從本地副本工作,可以掩蓋效率低下的訪問模式。

+1

我試着添加'restrict'關鍵字來告知編譯器緩衝區沒有共享,但問題仍然存在。我知道內存佈局很重要,但這真的是問題嗎?正如我在我的問題中提到的,問題只發生在CPU上。顯然,可以在GPU上完成優化。 –

+0

x86 CPU需要更多指令來執行「水平」算術運算,並將結果適當地打包以便通過SIMD(SSE/AVX)進行進一步處理,這正是OpenCL編譯器通常所編譯的內容。通常,GPU的結構基本上是不同的,並且被設計用於處理這種情況,因爲通常具有結構化頂點緩衝區。所以編譯器不重新排列數據,GPU只是更有效地處理它。 CPU在數組結構佈局上做得更好。 (請參閱:SOA vs AOS) – pmdj

+0

我剛剛檢查過,我在SSE或AVX中找不到任何水平乘法指令,所以這就是原因。編譯器可能會生成至少與乘法相同的「解包」指令。數據佈局很重要! – pmdj