2010-09-09 81 views
11

更新:我刚刚发现this documentation page。希望有一个从the documentation that I'd been using链接到它,它似乎是权威的API文档。但也许这是一个新的,未发布的工作。如何在Haskell Control.Parallel.Strategies中制定策略?

更新2:本文档为我提供了一个更好的主意,即如何使用Control.Parallel.Strategies模块。不过,我还没有完全解决这个问题......看问题的结尾。

我一直在尝试在Haskell中使用parListChunk或其他一些并行控制功能。但我无法弄清楚如何使用它们。警告:我是Haskell noob。大约20年前我学习了一些关于函数式编程的知识(!)。

这里是我的非并行功能:

possibKs n r = [ (k, (hanoiRCountK n k r)) | k <- [1 .. n-1] ] 

我想并行化,像这样幼稚的尝试:

possibKs n r 
    | n < parCutoff = results 
    | otherwise  = parListChunk parChunkSize results 
    where results = [ (k, (hanoiRCountK n k r)) | k <- [1 .. n-1] ] 

但该结构是不适合parListChunk。 文档说:

parListChunk :: Int -> Strategy a -> Strategy [a] 

parListChunk sequentially applies a strategy to chunks (sub-sequences) of a list in parallel. Useful to increase grain size

好,这就是我想要的。但如何使用它?我一直无法找到任何这样的例子。如果我理解类型声明,parListChunk是一个函数,它需要一个Int和一个Strategy<a>(借用C++参数化符号来帮助检查我是否真的理解这个权利),并返回Strategy<[a]>。在我的情况下,我正在处理Inta所以parListChunk将需要Int参数和Strategy<Int>。那么什么是Strategy,我该如何制作一个?一旦我成功使用了parListChunk,我该如何处理它所吐出的Strategy

Strategy type is defined这样的:

type Strategy a = a -> Done 

(这是所有的战略文件) 所以一个Strategy<Int>是一个函数,完成int类型返回的参数。显然它会导致它的论证在某个时间或某个时间得到评估。我在哪里得到一个,我应该使用什么样的?

以下功能似乎回报策略:

sPar :: a -> Strategy b 
sSeq :: a -> Strategy b 
r0 :: Strategy a 
rwhnf :: Strategy a 

但他们都不让你决定使用哪种类型的参数 - 它们产生Strategy<b>当你给参数a,否则你没有得到供应参数a!那是怎么回事??除此之外,我不知道这是什么意思。

我做了SO找到类似的功能parList being used的一个例子:

return . maximum $ map optimize xs `using` parList 

它使用这个时髦using功能,它宣称:

using :: a -> Strategy a -> a 

不够公平......在我的情况我可能想要a[Int],所以它需要一个Ints列表和一个Strategy<[Int]>和(做些什么?将策略应用于列表?并且)返回一个Ints列表。于是,我就跟着parList例子,改变了我的otherwise后卫:

| otherwise  = results `using` parListChunk parChunkSize 

但我必须承认,我仍然在黑暗中拍摄......我不能完全跟随周边类型签名。所以,这不是太奇怪,上面给出了一个错误:

Couldn't match expected type `[(Int, Integer)]' 
     against inferred type `a -> Eval a' 
Probable cause: `parListChunk' is applied to too few arguments 
In the second argument of `using', namely 
    `parListChunk parChunkSize' 
In the expression: results `using` parListChunk parChunkSize 

谁能告诉我用什么为Strategy a参数parListChunk?以及如何使用由parListChunk返回的Strategy [a]

新建部分

看着Basic Strategies,我想我需要使用rseq策略。大概。所以我尝试

| otherwise  = results `using` (parListChunk parChunkSize rseq) 

但GHC说rseq是“不在范围内”。 These API docs表示包中没有rseq,但sSeq似乎已将其替换。好的,所以我使用了sSeq,但它“不在范围内”。即使我正在导入Control.Parallel.Strategies

任何线索?顺便说一句我用来获取有关加载包这些消息:

Loading package deepseq-1.1.0.0 ... linking ... done. 
Loading package parallel-2.2.0.1 ... linking ... done. 

因此很明显,告诉我有什么版的水货包装:2.2.0.1。但是我在API docs中看不到有关此处描述的版本的信息。如果我不应该使用rseq或sSeq,我应该使用什么? Edward怎么能够使用parList?

回答

2

好的,我得到的代码工作。我把它用rwhnf,而不是rseq编译:

| otherwise  = results `using` (parListChunk parChunkSize rwhnf) 

this source coderwhnf在第3版改名为rseq所以我想我的并行包的版本已经过时了相对于this documentation。 :-S

我想这是使用“实验”包的价格的一部分。

无论如何,代码编译和运行。是否它对并行性有用是另一个问题...

+2

确保您使用+ RTS -N运行可执行文件以使用多个内核。如果启用+ RTS -s来显示统计信息,则可以看到跨核心传输工作的效率。为了更细致的调优,请使用ThreadScope(http://research.microsoft.com/en-us/projects/threadscope/)。 – 2010-09-09 22:07:02

+0

谢谢,@约翰。在WinGCHi中,我在GHCi启动选项中有“ghc --interactive-threaded”。我想这还不够?我可以在WinGCHi内运行多线程程序吗? – LarsH 2010-09-09 22:13:50

+0

IIRC ghci总是使用线程运行时(例如-threaded是隐式的)。只需在启动选项中指定你想要的运行时选项,你应该没问题。如果您不使用-N,则默认情况下即使使用线程运行时也要保留在一个内核上。 – 2010-09-09 23:23:18