如何确保 Data.Vector 的摊销 O(n) 级联?
我有一个应用程序,在其中使用向量作为代码的一部分是有效的。然而,在计算过程中我需要跟踪一些元素。我听说你可以从 Data.Vectors 获得 O(n) 摊销串联(通过通常的数组增长技巧),但我认为我做得不对。假设我们有以下设置:
import Data.Vector((++),Vector)
import Prelude hiding ((++))
import Control.Monad.State.Strict
data App = S (Vector Int)
add :: Vector Int -> State App ()
add v1 = modify (\S v2 -> S (v2 ++ v1))
在这种情况下,add
是否会在摊销 O(n) 时间内运行?如果没有,我怎样才能让 add
做到这一点(我需要在状态中存储 (forall s.MVector s Int)
吗?)。有没有更有效的方法来实现add
?
I have an application where it is efficient to use Vectors for one part of the code. However, during the computation I need to keep track of some of the elements. I have heard that you can get O(n) amortized concatenation from Data.Vectors (by the usual array growing trick) but I think that I am not doing it right. So lets say we have the following setup:
import Data.Vector((++),Vector)
import Prelude hiding ((++))
import Control.Monad.State.Strict
data App = S (Vector Int)
add :: Vector Int -> State App ()
add v1 = modify (\S v2 -> S (v2 ++ v1))
Does add
run in amortized O(n) time in this case? If not, how can I make add
do that (do I need to store an (forall s. MVector s Int)
in the State?). Is there a more efficient way of implementing add
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我也不太了解矢量库,所以我必须主要遵循一般原则。对它进行基准测试,运行一系列与您在应用程序中期望的类似的添加,并查看您获得的性能。如果它“足够好”,那就太好了,坚持使用简单的代码。如果没有,在状态中存储
(forall s.MVector s Int)
之前(你不能直接存储,元组不能保存 forall-types,所以你需要包装它) ,尝试通过转换为可变向量来改进添加行为,并在冻结之前执行串联以再次获得不可变向量,粗略地说,您可能需要在那里插入一些严格性。但是,如果 unsafeGrow 需要复制,则不能保证摊销 O(n) 行为。
则可以通过
I don't know the vector library well either, so I have to stick to general principles mostly. Benchmark it, run a sequence of adds similar to what you expect in your application and see what performance you get. If it's 'good enough', great, stick with the simple code. If not, before storing a
(forall s. MVector s Int)
in the state (which you can't directly, tuples can't hold forall-types, so you'd need to wrap it), try improving the add-behaviour by converting to mutable vectors and perform the concatenation there before freezing to get an immutable vector again, roughlyYou may need to insert some strictness there. However, if unsafeGrow needs to copy, that will not guarantee amortized O(n) behaviour.
You can get amortized O(n) behaviour by