如果值x
位于列表中,x
是某个功能
并在该列表中调用parList
(例如[l,x,l,x]
)
x
计算一次或两次?
根据我对Haskell的懒惰评估的理解,一旦x
被评估,它就不需要再次评估,因为它会返回相同的值。但是这适用于多线程环境吗?
答案 0 :(得分:7)
每当您为计算创建 spark 时
(这是parList
所做的)总有可能
该计算的工作将执行两次。
在实践中,这很少发生。基本上存在竞争条件
处理火花和主线程的线程之间。
Haskell通过初始设置变量的值来实现惰性 到 thunk - 本质上是指向计算值的代码的指针。 当需要变量的值时,Haskell运行指向的代码 通过thunk并用返回值替换thunk。 如果稍后使用该变量,Haskell只使用存储的值。
当您并行评估变量时,会创建 spark 指向 变量。当火花由后台线程处理时 只需要火花指向的价值。如果火花点 对于thunk,thunk运行并使用返回值进行更新。 如果火花指向已经评估的值,则没有任何反应 我们说火花失败。
因此,如果您并行评估[x,x,x,x,x,x]
之类的列表,则会产生一个火花
将为列表的每个元素创建,并且有可能
这些火花中的两个或多个将同时执行。也是
主线程可能会同时评估x
。
在这种情况下,计算x
的工作将会重复。
但是,一旦x
的thunk被更新,就没有火花或主线程
在此之后开始评估x
将重新计算x
。