2017-01-24 34 views
2

在閱讀了很多有關全球工作規模和當地工作規模的定義後,我仍然不太明白他們是什麼以及他們的工作方式。 我認爲全局工作大小決定了調用內核函數的次數,但是本地工作大小?本地和全球規模對程序執行的影響 - OpenCl

我認爲本地工作大小決定了多少線程將在同一時間同時使用,但我真的正確嗎?

本地大小是每個全局大小值執行一個內核程序的線程數量?我的意思是當我們有全局大小= 1和本地大小= 1時,那麼內核函數將被調用一次,並且只有一個線程正在處理它。 但是,當我們有全局大小= 4096和本地大小(如果允許這麼高)是1024,那麼我們有4096個內核函數調用,每個調用有1024個線程在同一時間工作?我對麼?

下面是一些示例代碼,我發現: enter image description here

,我的另一個問題是:如何局部尺寸變化影響的代碼? 正如我所看到的顯然是在global_id的工作,沒有本地的是如此是本地大小改變大於可以說1會影響執行該算法花費的時間?

當我們在該算法中使用for循環時,它是否會改變任何事情,然後考慮到本地大小的影響?我們是否需要使用local_id來查看改變本地大小時的差異?

我測試了一些我的程序,甚至當我僅使用global_id的變化的本地工作大小時,我的執行時間顯着縮短。 那麼它是如何工作的?我不明白。

預先感謝您!

回答

2

我認爲本地工作大小決定了多少線程將在同一時間同時使用 ,但我真的正確嗎?

正確,但它是每個計算單位,而不是整個設備。如果計算單元比本地線程組多,則設備未完全使用。當線程組多於計算單元但不是精確倍數時,某些計算單元在最後等待其他計算單元。當兩個值相等(或確切的倍數)時,那麼「多少次」對於完全佔用所有ALUS很重要。

例如,一個8核CPU可以定義8個計算單元(可能還有+8個硬件多線程)。但是具有相似價格的GPU可以具有20至64個計算單元。然後,即使在一個計算單元內,許多線程組也可以是「正在進行中的」,而不是明確調整的,但是由每個線程和每個計算單元以及可能每個gpu的資源使用情況而改變。

本地大小變化如何影響該代碼?正如我所看到的,顯然 在global_id上工作,沒有本地的變化到 更大,比說1會影響執行該算法花費的時間?

可矢量化/可並行化的內核代碼可以具有將線程分配給ALU,核心的SIMD或gpu計算單元的更寬SIMD的優點。對於CPU,可以同時發佈8個標量指令。對於GPU來說,它可能高達數千個。因此,當您將本地大小減小到1時,將並行線程問題的寬度限制爲1 ALU,這會削弱許多體系結構的性能。當您將本地大小設置得過大時,每個線程的資源會下降,並且性能會受到影響。如果你沒有任何想法,如果你給它的參數賦一個空值,opencl api可以爲你調整本地大小。

而當我們在該算法中有循環時,它是否會改變 什麼,然後關於局部尺寸的影響?我們是否需要使用 local_id來查看改變本地大小時的差異?

對於舊的和靜態的調度體系結構,建議使用展開步長等於基本SIMD寬度寬度的循環展開。不,本地ID只是查詢其計算單元中的線程ID,因此無需查詢是否不需要它。

我測試了幾個上我的節目,即使我只用 global_id不斷變化的地方工作的尺寸給我顯著較短 執行時間。那麼它是怎樣工作的?

如果內核需要瘋狂的資源,你可以想象每個本地組有1個線程。如果內核不需要除立即值之外的任何資源,則應使其最大值爲本地值。每個線程的資源分配(由於內核代碼)非常重要。新架構具有負載平衡功能,因此如果您讓api選擇最佳值,未來可能無關緊要。

爲了保持所有的ALU處於繁忙狀態,調度程序爲每個內核發出很多線程,當一個線程正在等待內存操作時,另一個線程可以同時執行ALU操作。當資源使用量很小時這很好。當您使用計算單元的所有資源的%50時,它只能有2個線程在運行。線程共享可共享的資源,如L1緩存,本地內存,寄存器文件。

代碼如c [i] = a [i] + b [i]對於標量浮點數是可以進行矢量化的。如果編譯器還沒有在後臺執行,你可以使用float8,float16和類似的結構來獲得更好的性能。這樣,它需要更少的線程來完成所有工作,並且訪問內存也更快。您還可以在內核中添加一個循環以更多地解除線程數量,這對於CPU來說是很好的,因爲在兩個數據塊之間需要較少的線程調度。對於GPU,它可能並不重要。用於CPU


簡單的例子:

4芯,本地大小= 10,全球大小= 100

芯1和2具有各3個線程組。核心3和4只有2個線程組。

  • 1:30個線程 - >充分高性能
  • 2:30個線程
  • 3:20個線程 - >少高性能,對其他作業
  • 4更好搶佔:20個線程

雖然指令流水線對於核1和核2沒有太多氣泡,但核3和核4在一段時間後會啓動氣泡,因此它們可用於其他作業,例如並行或操作系統或某些陣列中運行的第二個內核複製。當你平均使用所有內核,比如120線程時,他們每秒完成更多的工作,但是如果內核已經使用內存,CPU不能進行陣列拷貝。(除非OS爲其他線程搶佔)