2015-11-13 21 views
3

據我所知,虛擬方法調用是晚期綁定,因此不能由編譯器內聯。顯然,nvcc嚴重依賴內聯代碼。我想知道如果在Cuda的內核中使用虛擬方法會有什麼嚴重的缺點。有什麼情況應該避免它們?他們能對性能產生影響嗎?cuda虛擬方法的缺點

+1

除非在編譯時進行虛擬化,否則它們會帶來性能上的提升(它們會花費vtable查找+間接分支)。如果warp中的線程不解析爲相同的虛擬方法(例如處理具有不同具體類型的對象數組時),則會出現warp背離。儘可能避免它們。出於好奇,你在寫什麼類型的應用程序需要CUDA代碼中的虛擬方法? –

+0

這不是*方法*,它是「後期綁定」,它是方法*調用*,它是後期綁定。有時。 –

+0

我正在研究ODE求解器。長話短說,我有一個名爲_solve_的方法,它有兩個不同的實現。我用一個純虛函數和兩個覆蓋這個方法的子類寫了一個基類。這是一個易於維護的解決方案,雖然它可能不是最優的。不過,我想知道更多關於這個話題的信息。 – eaponte

回答

3

如果編譯器可以對該調用進行虛擬化,則可以將其轉換爲常規方法調用或甚至將其內聯。作爲NVCC的Clang/LLVM在某些情況下能夠做到這一點,作爲優化。您將不得不檢查生成的代碼,以瞭解是否屬於這種情況。

如果編譯器不能devirtualize通話,那麼它可能對性能產生影響,特別是如果該調用是一個熱門的路徑上。虛擬呼叫需要:

  1. vtable lookup;
  2. 間接分支。

vtable查找花費內存訪問,這是慢(可能「浪費」可能更好地使用緩存行)和間接分支一般是昂貴的。此外,如果並非所有線程中的線程都將虛擬方法解析爲相同的地址(例如,在處理具有不同具體類型的對象數組時),這將導致翹曲分歧,這又是一個性能問題。這就是說,如果你不是在熱路徑上調用虛擬方法,那麼影響應該可以忽略不計。沒有進一步的代碼,這是不可能的。

+0

我不熟悉間接分支的概念,你能解釋一下這是什麼嗎? – eaponte

+0

這個概念已經在網上徹底解釋了,從[Wikipedia]開始(https://en.wikipedia.org/wiki/Indirect_branch)。本質上,不是跳轉到編譯時已知的地址,而是跳轉到運行時已知的地址。 –

+0

@eaponte直接分支在指令中存儲目的地址,因此很容易繼續獲取分支的目標,它可以在獲取指令時查看並獲取目標地址。間接分支必須從內存中獲取一個值來查找它們的目標地址,因此指令獲取階段將不知道在哪裏繼續,直到可能長時間的內存訪問完成。 – doug65536