你如何多线程这段代码:
-- k: length of partition desired
-- n: number to make partitions from
integer_partitions :: Int -> Int -> [[Int]]
integer_partitions 0 _ = []
integer_partitions 1 n = [[n]]
integer_partitions k n =
do x <- [1..n - k + 1]
map (x:) (integer_partitions (k - 1) (n - x))
integer_partitions_par k n =
do x <- [1..n - k + 1]
map (x:) (integer_partitions (k - 1) (n - x))
variation_models ncars nlocations =
filter (both_conditions (adds_up_to nlocations) num_orderedq) $
integer_partitions ncars nlocations
我认为只有顶部的多线程才是最好的,但我们会在测试后看到
并行化纯代码的最简单方法是使用Control.Parallel.Strategies
。您可以尝试的第一件事是parMap rdeepseq
而不是map
,它为每个元素单独创建一个绿色线程,或者parListChunk n rdeepseq
使用n
块大小并在块内进行顺序评估。在这里,我使用parMap
来替换do
表示法提供的外部映射,而不是将每个x
附加到递归调用的内部映射。
integer_partitions_par :: Int -> Int -> [[Int]]
integer_partitions_par 0 _ = []
integer_partitions_par 1 n = [[n]]
integer_partitions_par k n = concat $ parMap rdeepseq
( x -> map (x:) (integer_partitions_par (k - 1) (n - x)))
[1..n - k + 1]
通常需要一些调整来平衡并行性优势和开销,而且我根本没有研究您的算法实际上会从并行中受益的地方。Haskell中的并行和并发编程对这个库有一个很好的介绍。
您确实需要使用-threaded
构建程序,并使用+RTS -N
调用它,以将-N
标志传递给 RTS(即 GHC 运行时系统(,以通知它使用与运行硬件上可用内核(或超线程(数相等的操作系统线程数。运行时调度程序将轻量级 Haskell 火花或绿色线程映射到可用的重量级系统线程上。