2010-08-22 30 views
3

「SIMT」體系結構的一些概念和設計對我而言仍然不清楚。OpenCL:關於SIMT執行模型的基本問題

從我所看到和閱讀的內容來看,分歧的代碼路徑和if()總是一個相當糟糕的主意,因爲許多線程可能會以鎖步方式執行。那究竟是什麼意思?什麼是這樣的:

kernel void foo(..., int flag) 
{ 
    if (flag) 
     DO_STUFF 
    else 
     DO_SOMETHING_ELSE 
} 

參數「標誌」是一切工作的單位和同一分支同樣是採取所有的工作單位。現在,GPU是否會執行所有的代碼,然後序列化所有的東西,並且基本上仍然採取未被採用的分支?或者它是否更聰明一些,只要執行了所採用的分支,只要所有線程都同意採用分支?這將永遠是這種情況。

I.e.序列化總是會發生還是僅在需要時纔會發生?對不起,這個愚蠢的問題。 ;)

回答

3

不,總是不會發生。只有條件在本地工作組中的線程之間不一致時才執行這兩個分支,這意味着如果條件評估爲本地工作組中工作項目之間的不同值,則當前代GPU將執行兩個分支,但只有正確的分支會寫出數值併產生副作用。

因此,保持一致性對於GPU分支的性能至關重要。

+0

我不完全稱它爲重要的。這是維護性能的重要因素。儘管取決於分支機構的複雜程度,但至少在目前爲止我遇到的大多數情況下,優化內存訪問(合併,避免銀行衝突,減少一般流量)要比確保分支機構評估相同的路徑(在某些情況下會對這些優化起作用)。 – Grizzly 2010-08-26 02:07:21

+0

@Grizzly這是至關重要的,如果你使用分支:) – 2010-08-26 20:39:16

1

對ati不太確定,但對於nvidia來說 - 它很聰明。 如果warp中的每個線程都採用相同的方式,則不會有序列化。

1

在你的例子中,flag對於所有的工作項都具有相同的值,所以一個好的編譯器會生成代碼,它將把所有的工作項都放在同一個方向上。

但考慮以下情況:

kernel void foo(..., int *buffer) 
{ 
    if (buffer[get_global_id(0)]) 
     DO_STUFF 
    else 
     DO_SOMETHING_ELSE 
} 

這不能保證所有的工作項目將採取相同的路徑,因此需要序列化或控制流的消除。

+0

決定是否代碼路徑分歧應該發生在硬件內部的情況下,這意味着您的示例序列化可能或可能不會發生,取決於值緩衝區(它可能只發生在某些工作組中,但不適用於其他工作組) – Grizzly 2010-08-26 02:11:04

+0

什麼是控制流消除?你能多解釋一下嗎?謝謝 – Zk1001 2011-10-19 06:30:27