2015-10-31 72 views
8

optimization guide of Beignet, an open source implementation of OpenCL targeting Intel GPUs如何充分利用OpenCL中的SIMD?

工作組大小應大於16和是多個的16

作爲根上兩個可能的SIMD通道是8或16。爲了不浪費SIMD 車道,我們需要遵循這個規則。

Compute Architecture of Intel Processor Graphics Gen7.5還提到:

對於基於Gen7.5產品,每個EU有七個線程總共通用寄存器文件的28千字節(GRF)。

...

在Gen7.5計算架構,最SPMD編程模型採用 這種風格的代碼生成和歐盟的處理器執行。實際上, 每個SPMD內核實例似乎在其自己的SIMD通道中串行且獨立地執行。

實際上,每個線程同時執行一個SIMD寬度的內核實例數。 因此,對於計算 內核的SIMD-16編譯,可能的是SIMD-16×7個=線程112個內核實例 是在單個EU同時執行。類似地,對於SIMD-32 x 7個線程= 224個內核實例在單個的 EU上同時執行。

如果我正確理解它,使用SIMD-16 x 7 threads = 112 kernel instances作爲示例,爲了在一個EU運行224個螺紋,工作組大小需要是16。然後OpenCL編譯器將摺疊16個內核實例爲16 SIMD線程,並在7個工作組上執行7次,並在單個EU上運行它們?

問題1:我是否正確?

但是OpenCL spec也提供矢量數據類型。因此,通過傳統的SIMD編程(如NEON和SSE)充分利用EU中的SIMD-16計算資源是可行的。

問題2:如果是這種情況,使用vector-16數據類型已經明確使用SIMD-16資源,因此刪除了每工作組至少16個項目的限制。是這樣嗎?

問題3:如果以上爲真,那麼如何兩個方法相互比較:1) 112螺紋摺疊成由OpenCL編譯7 SIMD-16線程; 2) 7個原生線程編碼爲明確使用vector-16數據類型和SIMD-16操作?

回答

1
  1. 差不多。您正在假設每個工作組有一個線程(在此上下文中的N.B.線程是CUDA稱爲「wave」的線程。在英特爾GPU中,說一個工作項目是GPU線程的SIMD通道)。如果沒有子組,則無法強制工作組大小完全成爲線程。例如,如果選擇WG大小爲16,編譯器仍然可以自由地編譯SIMD8並將其分佈在兩個SIMD8線程中。請記住,編譯器在WG大小已知之前選擇SIMD寬度(clCompileProgramclEnqueueNDRange之前)。 subgroups extension可能會允許您強制SIMD寬度,但絕對不會在GEN7.5上實現。

  2. OpenCL矢量類型是一個可選的顯式矢量化步驟,在已經自動發生的隱式矢量化之上。例如,您是否使用float16。每個工作項都將處理16個浮點數,但編譯器仍然會編譯至少SIMD8。因此,每個GPU線程將處理(8 * 16)浮動(儘管並行)。這可能有點矯枉過正。理想情況下,我們不希望通過使用明確的OpenCL矢量類型來明確地向量化我們的CL。但是如果內核沒有做足夠的工作(內核太短可能會很糟糕),它可能會有所幫助。某處說float4是一個很好的經驗法則。

  3. 我想你的意思是112個工作項目?通過本地線程你是指CPU線程還是GPU線程?

    • 如果你指的是CPU線程,那麼關於GPU的常用參數就適用。當你的程序沒有太多差異時(所有的實例採用相似的路徑),並且你使用足夠多的時間來減少傳輸GPU和GPU的成本(算術密度)時,GPU是很好的。
    • 如果你的意思是GPU線程(GEN SIMD8或SIMD16生物)。目前沒有(公開可見的)方式來明確編程GPU線程(編輯請參閱subgroups extension(在GEN7.5上不可用))。如果你能夠做到的話,它會和彙編語言相似。工作比較困難,編譯器有時會比我們做得更好,但是當您解決特定問題並獲得更好的領域知識時,通常可以通過足夠的編程工作做得更好(直到硬件更改和聰明的程序假設變爲無效)