[英]How do I write a parallel reduction using strategies in Haskell?
在高性能計算中,總和,產品等通常使用“並行縮減”來計算,該“並行縮減”采用n個元素並在O(log n )時間內完成(給定足夠的並行度)。 在Haskell中,我們通常使用折疊進行此類計算,但評估時間在列表長度中始終是線性的。
Data Parallel Haskell內置了一些內容,但是在列表的通用框架中呢? 我們可以用Control.Parallel.Strategies
做到嗎?
所以,假設f
是關聯的,我們如何寫
parFold :: (a -> a -> a) -> [a] -> a
所以parFold f xs
只需要時間length xs
對數?
我不認為列表是正確的數據類型。 因為它只是一個鏈表,所以必須按順序訪問數據。 雖然您可以並行評估項目,但在減少步驟中您將無法獲得太多收益。 如果你真的需要一個List,我認為最好的功能就是
parFold f = foldl1' f . withStrategy (parList rseq)
或者可能
parFold f = foldl1' f . withStrategy (parBuffer 5 rseq)
如果縮減步驟很復雜,您可以通過細分列表獲得收益,如下所示:
parReduce f = foldl' f mempty . reducedList . chunkList . withStrategy (parList rseq)
where
chunkList list = let (l,ls) = splitAt 1000 list in l : chunkList ls
reducedList = parMap rseq (foldl' f mempty)
我冒昧地假設你的數據是一個Monoid
for mempty,如果這是不可能的,你可以用你自己的空類型替換mempty,或者更壞的情況下使用foldl1'
。
這里有兩個來自Control.Parallel.Strategies
運算符。 parList
評估列表中的所有項目。 之后, chunkList
將列表分成1000個元素的塊。 然后通過parMap
並行減少這些塊中的每一個。
你也可以試試
parReduce2 f = foldl' f mempty . reducedList . chunkList
where
chunkList list = let (l,ls) = splitAt 1000 list in l : chunkList ls
reducedList = parMap rseq (foldl' f mempty)
根據工作的確切分配方式,其中一個可能比其他工作更有效。
如果您可以使用對索引具有良好支持的數據結構(數組,向量,映射等),那么您可以為縮減步驟執行二進制細分,這可能會更好。
這似乎是一個好的開始:
parFold :: (a -> a -> a) -> [a] -> a
parFold f = go
where
strategy = parList rseq
go [x] = x
go xs = go (reduce xs `using` strategy)
reduce (x:y:xs) = f x y : reduce xs
reduce list = list -- empty or singleton list
它有效,但並行性並不是那么好。 用parListChunks 1000
替換parList
有所幫助,但在8核機器上加速仍然限制在1.5x以下。
不確定你的parFold
功能應該做什么。 如果這是foldr或foldl的並行版本,我認為它的定義是錯誤的。
parFold :: (a -> a -> a) -> [a] -> a
// fold right in haskell (takes 3 arguments)
foldr :: (a -> b -> b) -> b -> [a] -> b
折疊將相同的函數應用於列表的每個元素,並累積每個應用程序的結果。 我想,提出它的並行版本將要求元素的函數應用程序並行完成 - 有點像parList
那樣做。
par_foldr :: (NFData a, NFData b) => (a -> b -> b) -> b -> [a] -> b
par_foldr f z [] = z
par_foldr f z (x:xs) = res `using` \ _ -> rseq x' `par` rdeepseq res
where x' = par_foldr f z xs
res = x `f` x'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.