使用多个处理器加速二叉树遍历Haskell(并行)

时间:2014-11-23 16:55:11

标签: haskell parallel-processing functional-programming multiprocessing binary-tree

按照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)))

我真的应该期待加速吗?我该如何实现呢?关于简化此代码的任何其他建议将不胜感激。

1 个答案:

答案 0 :(得分:2)

您的并行countBoxes需要NFData (Tree x)个实例才能在force Tree xleft上使用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整棵树......