2012-04-06 20 views
5

我必須解決GPU上的一個非常標準的問題,但我對實際的GPGPU頗爲陌生,所以我正在尋找解決此問題的方法。分段縮減與分散段

我在三維空間中有很多點被分配到極少數組(每個點屬於一個組),在這種情況下(特別是15)(不會改變)。現在我想計算所有組的均值和協方差矩陣。所以在CPU上是大致相同:

for each point p 
{ 
    mean[p.group] += p.pos; 
    covariance[p.group] += p.pos * p.pos; 
    ++count[p.group]; 
} 

for each group g 
{ 
    mean[g] /= count[g]; 
    covariance[g] = covariance[g]/count[g] - mean[g]*mean[g]; 
} 

由於組的數目是非常小的,最後一步可以將CPU(我需要在CPU上的值,反正)上進行。第一步實際上只是一個分段縮減,但是分散的部分。

所以我提出的第一個想法是首先按他們的小組排序。我想過使用atomic_inc來計算桶大小和每點重定位索引(對於排序有更好的想法?,原子可能不是最好的想法)。之後,他們按組進行排序,我可能會想出適應分段掃描算法here

但是在這種特殊情況下,我得到了大量的每點數據(9-10浮點數,如果需要的話可能甚至是雙精度浮點數),所以標準算法每個線程使用一個共享內存元素,點可能會使每個多處理器資源成爲共享內存或寄存器的問題(好吧,計算能力1.x比2.x要多得多,但仍然存在)。

由於組數非常少且不變,我認爲可能會有更好的方法。也許已經有適合這種標準問題的這些特定屬性的想法。或者,也許我的一般方法並沒有那麼糟糕,並且您有改進各個步驟的想法,例如適用於非常少量密鑰的良好排序算法或者一些分段縮減算法,以儘量減少共享內存/寄存器的使用。

我正在尋找一般方法,不想使用外部庫。 FWIW我正在使用OpenCL,但它並不重要,因爲GPU計算的一般概念在主要框架上並沒有真正的差異。

+1

這是一個很常見的模式。使用Thrust,首先需要'sort_by_key'將每個段中的數據放在一起,然後'reduce_by_key'來計算每個組的均值和協方差。 – 2012-04-06 23:28:34

回答

1

即使組數很少,我認爲您仍然可以避免將組分初始分組,同時仍然保持降低步驟的效率。您可能還想執行完整排序,而不僅僅是排序索引,因爲這將有助於在還原步驟中保持內存訪問效率。

的分類,瞭解一般的策略在這裏:

http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter46.html

,爲削減(老了,但還是不錯的):

http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf

示例實現並行減少比例爲:

http://developer.nvidia.com/cuda-cc-sdk-code-samples#reduction