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