按照Chapter 24 of "Real World Haskell"和Chapter 2 of "Parallel and Concurrent Programming in Haskell"中的示例,我设法构建了以下函数,以便使用多个处理器快速构建和遍历二叉树。
import Control.Parallel (par, pseq)
import Control.DeepSeq
data Tree x = Empty | Node x (Tree x) (Tree x) deriving (Show, Read, Eq)
-- Create instance of NFData for Tree data type (defining "normal form")
instance NFData a => NFData (Tree a) where
rnf Empty = ()
rnf (Node x l r) = rnf x `seq` rnf l `seq` rnf r
-- Recursive function to build a tree using multiple processors simultaneously
copyBoxPar :: Int -> Tree Int
copyBoxPar x
| x <= 0 = Empty
| x > 0 = force left `par` (force right `pseq` (Node x (left)(right)))
where
left = copyBoxPar (x-1)
right = copyBoxPar (x-1)
-- Serial recursive function to count leaves in tree
countBoxes :: Tree x -> Int
countBoxes Empty = 0
countBoxes (Node x left right) = 1 + countBoxes (left) + countBoxes (right)
我可以验证使用上述功能,与串行等效产品相比,使用6个CPU的速度提高了2倍以上。
但是,如果可以的话,我想加快速度。
在我看来,实现countBoxes函数的并行版本应该有所帮助,但是当我尝试用下面的并行代码替换countBoxes的定义时,我得到一个错误&#34;没有实例(NFData x)使用&#39; force&#39;&#34;。
-- Parallel function to count leaves in tree
countBoxes :: Tree x -> Int
countBoxes Empty = 0
countBoxes (Node x left right) = force left `par` (force right `pseq` (1 + countBoxes (left) + countBoxes (right)))
我真的应该期待加速吗?我该如何实现呢?关于简化此代码的任何其他建议将不胜感激。
答案 0 :(得分:2)
您的并行countBoxes
需要NFData (Tree x)
个实例才能在force
Tree x
和left
上使用right
。您可以通过将NFData x
添加到countBoxes
的类型签名的上下文来要求存在一个。
-- Parallel function to count leaves in tree
countBoxes :: NFData x => Tree x -> Int
...
NFData x
足以从NFData (Tree x)
中推断instance NFData a => NFData (Tree a)
。
我建议您尝试运行此功能,以了解它如何影响性能。也许并行的countBoxes
不应该能够force
整棵树......