什么时候`修改`复制矢量?

时间:2017-08-23 12:43:31

标签: performance haskell vector functional-programming immutability

来自https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector.html#v:modify

  

对矢量应用破坏性操作。如果安全的话,操作将在适当的位置执行,否则将修改矢量的副本。

这听起来可能具有截然不同的性能特征,这取决于在适当的位置修改矢量是否被视为“安全”。这激发了问题......

何时进行修改,以及何时复制向量?是否有某种方法可以通过使用类型系统来确保进行适当的修改?

1 个答案:

答案 0 :(得分:11)

修改调用具有以下重写规则的Data.Vector.Generic.modify的调用clone

"clone/new [Vector]" forall p.
  clone (new p) = p

因此,当某些内容处于new p的句法形式时,它不会被复制。它显示为modifysliceinittailtakedropunstreamclone是融合在这里的主要因素。这与流融合工作(用于深度潜水的谷歌能力论文)密切相关,这是支持矢量设计的基础。

编辑:根据你的评论我会详细说明。只有语法new p形式的东西才能避免复制。由于您可能不是自己编写new,因此它只会出现在向量包中内联使用函数的结果。查看向量1,我上面确定的函数似乎使用了new,因此如果事情是内联的,那么modify就不允许复制 只保留新颖性,矢量仍然需要通过createforcemodifyunstream之类的新构造。

例如,如果您有代码:

v = fromList [1..10]
g = modify f v
f = undefined

然后v将被内联,而向量的格式为new p(因为fromList使用unstream new},因此{{1}不必复制数组。

另一方面,请考虑:

modify

现在v = let v0 = fromList [1..10] in {-# NOINLINE v #-} g = modify f v 没有显式内联 - 它也可能无法内联,因为它来自不同的模块或表达式是共享的。因此,没有代码语法 v,并且重写规则不会触发。

不那么做作,请考虑:

modify f (new p)

这是一个常见的模式,其中向量被读取和修改 - 显然在读取之前无法修改,并且重写规则要么不会被激活(因为那里没有g = let v = fromList [1..10] t = v ! 4 v2 = modify f v in t + (v2 ! 4) )或者你我将不得不失去new的分享。

1例如,请参阅here规则“slice / new [Vector]”。