gpt4 book ai didi

performance - Haskell:Verlet 集成的缓慢无限列表

转载 作者:行者123 更新时间:2023-12-04 02:29:06 28 4
gpt4 key购买 nike

我正在使用 Haskell 制作 Verlet 积分器来模拟重力。积分器使用对象的前两个位置作为种子,并在此后生成其余位置。

我认为在 Haskell 中实现此目的的一个好方法是使用无限列表。然而,当实现时,我发现它在很长时间内运行得非常慢(Haskell 1700 时间步长:12 秒,Python 1700 时间步长:< 1 秒)

以下是具有类似性能的一维积分器的相关代码:

verletStep dt acc xn xn1 = 2*xn1 - xn + (acc xn1)*dt*dt

verlet dt acc x0 x1 = x0 : x1 : next (verlet dt acc x0 x1)
where
next (xn : xs@(xn1:_)) = (verletStep dt acc xn xn1) : next xs

我还尝试使用 zipWith 生成无限列表,但它具有相似的性能。

为什么要花这么长时间?垃圾收集本身大约需要 5 秒。有没有什么好方法可以让它运行得更快?

最佳答案

这个定义...

verlet dt acc x0 x1 = x0 : x1 : next (verlet dt acc x0 x1)
where
next (xn : xs@(xn1:_)) = (verletStep dt acc xn xn1) : next xs

...导致 verlet dt acc x0 x1 被不必要地计算多次,从而构建大量不需要的列表。这可以通过手动计算时间步来看出:

verlet dt acc x0 x1
x0 : x1 : next (verlet dt acc x0 x1)
x0 : x1 : next (x0 : x1 : next (verlet dt acc x0 x1))
x0 : x1 : (verletStep dt acc x0 x1) : next (x1 : next (verlet dt acc x0 x1))

解决方案是消除不必要的列表构建:

verlet dt acc x0 x1 = x0 : x1 : x2 : drop 2 (verlet dt acc x1 x2)
where
x2 = verletStep dt acc x0 x1

drop 2 删除列表的前两个元素(在本例中为 x1x2,我们已经预先添加了它们)。 verlet 使用第二个位置 x1 和新计算的第三个位置 x2 递归调用。 (与原始定义相比,其中 verlet 使用相同的参数递归调用。这应该引起怀疑。)

关于performance - Haskell:Verlet 集成的缓慢无限列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31875005/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com