2013-11-25 62 views
1

我在OpenCL中看到了smallpt實現,作者在內核中使用了自己的矢量類型和前置宏函數。在OpenCL中使用自己的矢量類型似乎更快

typedef struct { float x, y, z; } Vec; 

#define vinit(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; } 
#define vsmul(v, a, b) { float k = (a); vinit(v, k * (b).x, k * (b).y, k * (b).z) } 
#define vdot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) 
#define vnorm(v) { float l = 1.f/sqrt(vdot(v, v)); vsmul(v, l, v); } 
and much more... 

我測試了代碼,並用標準的內建float3類型替換了用戶定義的矢量類型和操作。我驚訝於作者的原始實現比內置float3的變體快10幀。之後,我用英特爾OpenCL應用程序內核生成器測試了一些情況,似乎證實內置函數速度較慢。

任何想法爲什麼?供應商推薦內置矢量化類型:/

+0

這是什麼語言? C或C++中沒有內建類型'float3'。 –

+0

你的基準測試代碼是什麼樣的?你在運行什麼硬件? –

+0

這是基於CGP標準的OpenCL C,用於GPGPU編程。 基準測試代碼簡單地運行一百萬次以上的基本矢量操作,並將其與用戶定義的版本進行比較。 (norm,cross,dot,add,mull,...) 基準測試的硬件是Intel i7-3630QM(Intel HD 4000沒有在內核生成器中工作)。並且在我的nvidia quadro gpu(NVS 5200M)上運行smallpt代碼 這裏是原始的smallpt opencl實現http://www.phoronix-test-suite.com/benchmark-files/SmallptGPU-v1.6pts-1。 tar.bz2 – Erabong

回答

2

用戶定義的矢量是一個真正的3元素矢量,使用3個浮點大小。 然而,OpenCL的float3矢量是真正使用float4載體,如可以在cl_platform.h可以看出:

/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */ 
typedef cl_float4 cl_float3; 

最初使用的載體是針對OpenCL推薦的編程技術。由於與簡單的非矢量代碼相比,完整的SIMD架構被利用。但是隨着OpenCL編譯器的發展,現在編譯器足夠聰明,可以在內部矢量化用戶代碼。 有時候(我也看到了它與其他內核一樣,即使是我自己也是如此),最好用純元素編寫代碼,讓編譯器重新對其進行矢量化,而不是使用默認矢量類型。因此,我建議,除非矢量簡化了編程任務,並且可以讀取(例如2D處理等),現在不要使用OpenCL矢量。

也許用戶定義的vector3正在使用較少的寄存器,並且溢出較少。或者也可能是另一種向量佈局對於算法更好,並且編譯器可以自由地在用戶定義的向量案例中重新構造代碼。

應該使用已編譯的PTX代碼對發生的事情進行獨立分析。

+0

提高可讀性和一致性非常重要。 – Thomas

+0

NVIDIA硬件不是矢量硬件,因此編譯器會標量所有內置矢量類型。此外,一些編譯器會這樣做,然後重新向量化您的代碼,以便多個工作項形成一個執行路徑。換句話說,如果4個工作項目符合SSE或AVX向量類型,那麼向量代碼將一次在一個核心上運行四個工作項目。這與您在代碼中使用矢量類型無關。 AMD的上一代硬件是矢量化的,並且可以使用OpenCL C矢量類型。他們最新的硬件是標量。 – Dithermaster

+0

@Dithermaster是的,我在AMD OpenCL優化指南中看到了這個。 因此,總而言之,您認爲最好的解決方案是儘可能快地處理在所有平臺上運行向量代碼的問題。 – Erabong

1

添加一點。對於NVIDIA GPU(我不瞭解AMD),有32位(LD.32),64位(LD.64)和128位(LD.128)加載指令,但沒有96位加載。從DRAM中加載一個真正的float3被實現爲兩個獨立的指令 - 一個LD.32和一個LD.64。如果你正在爲一個float2,double或者float4連續加載連續的線程中的float3,你實際上是通過兩個單獨的指令以96比特的步長訪問數據,導致重放。商店說明也是如此。我猜想這是選擇typedef爲float4的原因。