2011-11-21 55 views
4

作爲一個更大的問題的一部分,我試圖定義一個數組裏的數組像這樣:導致惹巴嵌套數組定義的「執行嵌套並行計算順序...」

import Data.Array.Repa 
type Arr = Array DIM2 Int 

arr = force $ fromList (Z :. 5 :. 5) [1..25] :: Arr 

combined :: Arr 
combined = arr `deepSeqArray` 
    traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) (\f (Z :. x :. y) -> 
     let reg = force $ extract f (x,y) (2,2) 
     in reg `deepSeqArray` sumAll reg) 

extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Arr 
extract lookup (x0,y0) (width,height) = fromFunction bounds 
    $ \sh -> offset lookup sh 
    where 
    bounds = Z :. width :. height 
    offset :: (DIM2 -> Int) -> DIM2 -> Int 
    offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0) 

main = print combined 

extract功能是使用fromFunction和提供給它的查找函數,但它也可以使用traversearr ! ...獲得相同的效果。儘管使用forcedeepSeqArray到處儘早,控制檯充滿了這裏的消息,再加上正確的結果:

Data.Array.Repa:執行嵌套並行計算順序。 你可能已經調用了'force'函數,而另一個實例是 已經在運行。如果第二個版本因延遲評估而暫停 ,則可能會發生這種情況。在'強制'下一個數組之前,使用'deepSeqArray'確保每個數組完全被 評估。

雖然我還沒有構建一個帶有列表的版本來比較速度,但在更大的版本中,性能卻受到了影響。

這是否僅僅是嵌套數組定義的結果,因此我應該重構我的程序,使內部或外部定義成爲列表?我的extract功能可怕並且問題的原因是什麼?

提示from this question對我們來說非常有用,但我還沒有通過編譯代碼進行爬取。

回答

2

這是因爲'print'隱式強制數組。內部的'force'和'sumAll'函數調用並行計算,但'打印',所以你有嵌套的並行。事實上,這是非常明顯的是在Repa 2 API中非常悲傷。

Repa3通過導出'force'和'sumAll'的順序和並行版本等解決了這些問題。它還向數組類型添加了一個標記,以指示數組是否延遲或顯示。 Repa 3尚未完成,但您可以使用http://code.ouroborus.net/repa上的頭版。在今年晚些時候的GHC7.4之後,它應該是不夠用的。

這是您的示例的Repa3版本,其運行時未提供關於嵌套並行性的警告。請注意,'force'現在是'compute'。

import Data.Array.Repa 

arr :: Array U DIM2 Int 
arr = fromListUnboxed (Z :. 5 :. 5) [1..25] 

combined :: Array U DIM2 Int 
combined 
    = computeP $ traverse arr (\_ -> Z :. 4 :. 4 :: DIM2) 
    $ \f (Z :. x :. y) -> sumAllS $ extract f (x,y) (2,2) 

extract :: (DIM2 -> Int) -> (Int,Int) -> (Int,Int) -> Array D DIM2 Int 
extract lookup (x0,y0) (width,height) 
    = fromFunction bounds 
    $ \sh -> offset lookup sh 
    where 
    bounds = Z :. width :. height 
    offset :: (DIM2 -> Int) -> DIM2 -> Int 
    offset f (Z :. x :. y) = f (Z :. x + x0 :. y + y0) 

main = print combined