我在Haskell学习并行性.我见过这段代码:
runEval $ do
a <- rpar (f x)
b <- rpar (f y)
rseq a
rseq b
return (a,b)
Run Code Online (Sandbox Code Playgroud)
它在性能和开销方面有什么区别?
let a = f x
let b = f y
(a, b)
Run Code Online (Sandbox Code Playgroud)
也就是说,根本没有使用Eval.对我来说,第二个具有相同的性能和更少的开销.
这完全取决于什么f.如果f您的系统需要很长时间进行计算,并且您的系统具有备用CPU核心,那么并行版本将更快完成.
如果f是一些细小的像f n = n + 1那么当然标准的单线程版本将会更快.创建Haskell线程的开销相当低,但并不是那么低.(如果你只有一个执行上下文,那么当然没有任何意义).
请注意,如果我们将开销定义为"系统执行与计算结果无直接关系的工作",则第一个版本总是有更多"开销".但是,如果你到评估f x和f y并行,可能会更快地完成,即使系统已经"浪费"一些上的开销它的执行资源.我们可能将并行版本的运行时间近似为:
maximum(time for f x, time for f y) + overhead
Run Code Online (Sandbox Code Playgroud)
标准版的运行时间如下:
time for f x + time for f y
Run Code Online (Sandbox Code Playgroud)
因此,如果两个调用中较小的一个f比并行化开销花费更多的时间,那么并行版本是值得的.
当然,实际上它可能要复杂得多.一个这样的问题:如果f x和f y共享引用相同的thunk,则标准顺序版本完全共享工作,而并行版本可能会意外地浪费时间让两个线程执行thunk.尤其是,如果大部分的工作f x,并f y在实际上减少thunks来获得f准备申请,那么你就不是"真的" parallelising在所有这些工作(而不是更多或更少的赛车两个线程,看看哪个先完成).
最终,您需要使用测量和判断来决定应用并行性的位置.这不是你可以盲目添加并自动获得好处的东西(否则编译器会为你做).
但是如果你尝试并行运行两个非常简单的计算,它肯定不会给你任何好处.如果你只是在玩并行性以了解它是如何工作的,那么尝试编写一个f能够完成足够工作的函数,使你的第二个版本运行至少几秒钟,然后查看并行版本是否是快点.