Optimization Haskell:列表/向量/阵列性能调整
我正在尝试Haskell来计算统计物理中模型的配分函数。这涉及到遍历相当大的配置列表和对各种观察值求和——我希望尽可能高效地这样做 我的代码的当前版本如下: 当尝试在列表和向量之间进行选择以枚举配置时,会发生一些奇怪的事情;特别是,要截断列表,请使用Optimization Haskell:列表/向量/阵列性能调整,optimization,haskell,data-structures,vector,Optimization,Haskell,Data Structures,Vector,我正在尝试Haskell来计算统计物理中模型的配分函数。这涉及到遍历相当大的配置列表和对各种观察值求和——我希望尽可能高效地这样做 我的代码的当前版本如下: 当尝试在列表和向量之间进行选择以枚举配置时,会发生一些奇怪的事情;特别是,要截断列表,请使用V.toList。取(3^n)。V.fromList(其中V是Data.Vector)比仅仅使用take更快,这感觉有点违反直觉。在这两种情况下,列表都是惰性评估的 列表本身是使用迭代构建的;相反,如果我尽可能多地使用Vectors,并使用V.ite
V.toList。取(3^n)。V.fromList
(其中V
是Data.Vector
)比仅仅使用take
更快,这感觉有点违反直觉。在这两种情况下,列表都是惰性评估的
列表本身是使用迭代
构建的;相反,如果我尽可能多地使用Vector
s,并使用V.iterateN
构建列表,那么它会再次变慢
我的问题是,有没有一种方法(除了在代码中的任意位置拼接
V.toList
和V.fromList
)来预测哪种方法最快?(顺便说一句,我使用当前稳定版本的ghc-O2编译所有内容。)向量是严格的,并且有O(1)个子集(例如take)。它们还具有优化的插入和删除功能。因此,您有时会看到通过动态切换数据结构来提高性能。然而,这通常是错误的方法——以一种或另一种形式保存所有数据更好。(您也在使用uarray,这进一步混淆了问题)
一般规则:
- 如果数据很大且仅以批量方式进行转换,则使用密集、高效的结构(如向量)是有意义的
- 如果数据很小,并且很少线性遍历,那么列表就有意义
迭代时。列表上的replicate
是O(n),但在向量上使用相同的惰性方法不一定会有同样的效率(您应该更喜欢向量中的内置方法来生成数组)
一般来说,向量对于数值运算应该总是更好的。可能您必须使用列表中的不同函数
我只会坚持向量。避免使用UARRAY,并避免列表作为生成器。BTW
-funbox严格字段将有助于您的统计数据类型。确实如此!总的来说,使用它的速度提高了约10%。。。像这样的优化是一种乐趣:-)BTW-我做了一个基准实现在C++中,使用相同的算法以势在必行的方式使用STD::vector。在我的计算机上,N=15,Haskell版本在4.6秒内完成,C++的大约在1.8秒内完成。我想说这是非常令人满意的:-)谢谢你的答复。事实上,混合看起来是错误的(这就是我为什么要问这个问题),但我尝试的所有“统一”方式最终都比我现在使用的奇怪的混合方式慢,有时慢3到4倍。也许我错过了一个。。。我会尝试其他东西!关于避免UArray
s:我尝试用V.acum
或V.acculate
替换accumaray
,它们似乎是等效的,而且速度稍慢,这就是为什么我选择了阵列选项。