2014-02-21 34 views
0

我在GPU內存中有一個大的矩形矩陣NxM,以逐行表示形式存儲爲一維數組。讓我們說這個矩陣實際上是由大小爲nxm的子矩陣組成的。爲了簡單起見,假設N是n的倍數並且與M和m相同。讓我們說,數組的數據類型是float或double。CUDA:如何在子矩陣中找到極值的索引?

尋找每個子矩陣中極值指數的有效方法是什麼?例如,如何找到每個子矩陣的最大元素的一維索引,並在某些數組中記下這些索引。

+0

最合適的解決方案取決於'n'相對於翹曲尺寸的大小。沒有一個通用的解決方案。如果n接近'N',那麼'cublasIsamin'可能和你自己寫的任何東西一樣有效。 – talonmies

+0

@talonmies我試着在我的回答中指出這個重要的區別(是否N = n * 2或N = n * 10000)。雖然'cublasIsamin'聽起來像是我繪製的第二種方法的好選擇,但問題是隻能在一維數組上運行(在incx中給定可能的步幅,但仍然是1D) - 所以它不適用於2D子矩陣 – Marco13

回答

2

我簡直不能想象的要所以自信(或者傲慢?)說,一個特定的解決方案是做什麼的「最有效的方式」

然而,一些想法(不要求覆蓋「最有效」的解決方案):

我認爲基本上有接近這一

  • 對於所有子的兩個「垂直」方式在並行矩陣:查找極值依次
  • 的對於子矩陣順序所有:查找並行

的問題,其中一個極值更合適的可能取決於矩陣的大小。您提到「N是n的倍數」(對於M和m類似)。讓大小爲M x N的矩陣由大小爲m x na*b子矩陣組成。

對於第一種方法,我們可以簡單地讓每個線程需要一個子矩陣的護理,用一個簡單的循環一樣

for (all elements of my sub-matrix) max = element > max ? element : max; 

這裏的前提是a*b是「相當大」。也就是說,當你可以啓動這個內核時,假設有10000個子矩陣,那麼這可能已經帶來了很好的加速。

與此相反,在第二種方法中,每個內核(及其所有線程)將處理一個子矩陣。在這種情況下,內核可能是一個標準的「減少」內核。 (這種減少常常是「計算數組元素的和/積」的一個例子,但它適用於任何二進制關聯操作,所以不用計算總和或乘積,可以基本上使用相同的內核來計算最小或最大)。因此,內核將針對每個子矩陣啓動,並且這隻有在子矩陣「相當大」時纔有意義。

但是,在均爲的情況下,必須考慮一般性能準則。特別是,因爲在這種情況下,操作顯然是內存限制的(而不是計算限制的),所以必須確保對全局內存(即對於矩陣本身)的訪問被合併,並且佔用由內核創建的越高越好。

編輯:當然,可以考慮以某種方式結合這些方法,但我認爲他們至少展示了可用選項空間中最重要的方向。