你好。给出的代码:
import Control.DeepSeq
import Control.Exception
import Control.Parallel
import Control.Parallel.Strategies
import System.Environment
import Text.Printf
l = [34,56,43,1234,456,765,345,4574,58,878,978,456,34,234,1234123,1234,12341234]
f x = Just (sum [1..x])
fun1 :: [Maybe Integer]
fun1 = map f l `using` parList rdeepseq
fun2 :: [Maybe Integer]
fun2 = map f l `using` evalList (rparWith rdeepseq)
fun3 :: [Maybe Integer]
fun3 = map f l `using` evalList (rpar . force)
main :: IO ()
main = print fun1
为什么fun1和fun2会按顺序运行? 根据我理解,rparWith应该会触发其参数的Spark。这里here的答案也是这样说明的。但是对于fun1和fun2,我得到的输出是“SPARKS: 0(0转换,0溢出,0无用,0 GC'd,0失败)”。因此,甚至没有创建Sparks。 fun3按预期工作,并且创建了Sparks。 感谢你的帮助。
更新:我发现rdeepseq使书中的示例(Haskell并行与并发编程)按顺序工作。书上说:
我们可以使用parPair编写一个完全并行评估一对组件的策略: parPair rdeepseq rdeepseq :: (NFData a, NFData b) => Strategy (a,b)
当将此策略应用于一对组件时,parPair调用evalPair,在每个组件上调用rparWith rdeepseq。因此,效果是每个组件都将在并行中完全评估为正常形式。
但是如果我运行
(Just (fib 35), Just (fib 36)) `using` parPair rdeepseq rdeepseq
甚至更多。
(fib 35, fib 36) `using` parPair rdeepseq rdeepseq
Threadscope显示只有一个核心正在运行,且未创建任何火花。
类似于此实现的fibonacci(也来自该书)
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
-threaded
并使用+RTS -Nx
运行可执行文件,其中x
是要使用的核心数。你在测试中这样做了吗? - AJF(Just (fib 35), Just (fib 36)) \
using` evalPair (rparWith (rseq . force)) (rparWith (rseq . force))显示了 2 个核心繁忙,但是
(Just (fib 35), Just (fib 36)) `using` parPair rdeepseq rdeepseq` 只有一个。据我所知,它们应该是等价的。 - Mikekekeke