Haskell 评估、rpar和rseq——有什么好处吗?

Haskell 评估、rpar和rseq——有什么好处吗?,haskell,parallel-processing,Haskell,Parallel Processing,我在Haskell学习并行性。我看到了以下代码: runEval $ do a <- rpar (f x) b <- rpar (f y) rseq a rseq b return (a,b) 也就是说,根本不使用Eval。对我来说,第二个具有相同的性能和更少的开销。这完全取决于f的功能。如果f需要很长时间才能让您的系统进行计算,并且您的系统有一个备用的CPU内核,那么并行版本将完成得更快 如果f很小,比如fn=n+1,那么标准的单线程版本当然会更快。创建Has

我在Haskell学习并行性。我看到了以下代码:

runEval $ do
  a <- rpar (f x)
  b <- rpar (f y)
  rseq a
  rseq b
  return (a,b)

也就是说,根本不使用
Eval
。对我来说,第二个具有相同的性能和更少的开销。

这完全取决于
f
的功能。如果
f
需要很长时间才能让您的系统进行计算,并且您的系统有一个备用的CPU内核,那么并行版本将完成得更快

如果
f
很小,比如
fn=n+1
,那么标准的单线程版本当然会更快。创建Haskell线程的开销相当低,但并没有那么低。(当然,如果只有一个执行上下文,那么就没有意义了)

请注意,如果我们将开销定义为“系统所做的与计算结果没有直接关系的工作”,那么第一个版本总是有更多的“开销”。但是,如果您并行地评估
fx
fy
,您可能会更快地完成,即使系统在开销上“浪费”了一些执行资源。我们可以将并行版本的运行时间近似为:

maximum(time for f x, time for f y)  +  overhead
time for f x  +  time for f y
标准版本的运行时间为:

maximum(time for f x, time for f y)  +  overhead
time for f x  +  time for f y
因此,只有当两个
f
调用中较小的调用所花费的时间明显大于并行化开销时,并行版本才值得

当然,在现实中,情况可能要复杂得多。其中一个问题是:如果
fx
fy
共享对相同thunk的引用,那么标准顺序版本将完全共享工作,而并行版本可能会意外地浪费时间,让两个线程执行thunk。特别是,如果
fx
fy
的大部分工作实际上是减少thunks以使
f
准备好应用,那么您根本就没有“真正”并行这项工作(而是或多或少地运行两个线程以查看哪个线程先完成)

最终,您需要使用度量和判断来决定在何处应用并行性。它不是你可以盲目添加并自动获得好处的东西(否则编译器会帮你做)


但是如果您试图并行运行两个非常简单的计算,它肯定不会给您带来任何好处。如果您只是在玩弄并行性来了解它是如何工作的,那么尝试编写一个函数
f
,该函数可以做足够的工作,使您的第二个版本至少需要几秒钟才能运行,然后查看并行版本是否更快。

并且您的系统有一个备用CPU核心,然后并行版本将更快地完成。
——但是我们通过调用
rseq
,等待它们都完成,因此,即使第一个版本完成得很快,它也必须在之后等待第二个版本。那么并行调用而不是顺序调用它们有什么好处呢?@Daaka好处是运行时间越短,而运行时间越长。所以你只需要等待时间越长越好,而不是越长越短。同样,为了值得去做,你通常希望他们两个都花上合理的时间。比如说,6秒和4秒。如果按顺序运行,则需要10秒。如果你并行运行它们,只需要6分钟(加上开销,这在人类时间里是看不到的)。具体数字:如果你有两个30分钟和40分钟的作业,并行版本需要40分钟加上开销。顺序版本需要70分钟。假设您第一次呼叫
rseq
是为了40分钟的工作。这需要40分钟,但下一个电话会立即返回,因为这项工作已经完成了10分钟。如果对
rseq
的调用被反转,第一个调用需要30分钟,第二个调用需要额外的10分钟(因为这是40分钟作业剩下的全部时间)。无论哪种方式,对
rseq
的两个调用的总运行时间都是40分钟。