【问题标题】:Fast multi-body gravity algorithm?快速多体重力算法?
【发布时间】:2011-12-28 05:39:15
【问题描述】:

我正在编写一个程序来模拟 n 体重力系统,其精度任意好取决于我在每一步之间采取的“时间”步长有多小。现在,它对多达 500 个物体的运行速度非常快,但在那之后它变得非常慢,因为它必须通过一个算法来确定每次迭代时每对物体之间施加的力。这是复杂度 n(n+1)/2 = O(n^2),所以它很快变得非常糟糕也就不足为奇了。我想最昂贵的操作是我通过取平方根来确定每对之间的距离。因此,在伪代码中,这就是我的算法当前的运行方式:

for (i = 1 to number of bodies - 1) {
  for (j = i to number of bodies) {
   (determining the force between the two objects i and j,
    whose most costly operation is a square root)
  }
}

那么,有什么办法可以优化这个吗?有什么花哨的算法可以通过快速修改重用过去迭代中使用的距离吗?有什么有损方法可以减少这个问题吗?也许通过忽略 x 或 y 坐标(它是二维的)超过一定数量的物体之间的关系,由它们的质量的乘积决定?抱歉,如果这听起来像我在漫无边际,但我能做些什么来加快速度吗?我宁愿保持任意精确,但如果有解决方案可以降低这个问题的复杂性,但会牺牲一点精确度,我很想听听。

谢谢。

【问题讨论】:

  • 也许我很密集,但你不知道用 sqrt(x^2 + y^2) 得到距离,然后立即用 G*m1*m2/r^2 平方到得到力量?你不能完全去掉平方根吗?
  • @JamesMoughan 这行不通。因为你不想计算力的绝对值,而是力矢量。在这个公式中你得到r_vec/Abs(r)^3
  • 但这里的主要问题不是平方根的成本。这是该算法在对象数量上是二次方的。使用将对象组合在一起的近似值,您可以将其缩减为 n*log(n) 或类似的东西。
  • 你可以像詹姆斯所说的那样把平方根全部去掉。我刚刚测试了两种方式,结果相同。

标签: java optimization simulation gravity


【解决方案1】:

一种好的有损方法是运行clustering algorithm 将主体聚集在一起。

some 聚类算法的速度相当快,诀窍是不要在每个滴答声中都运行聚类算法。而是每隔 C 滴答 (C>1) 运行一次。

然后对于每个簇,计算簇中所有物体之间的力,然后为每个簇计算簇之间的力。

这将是有损的,但我认为这是一个好方法。

你必须摆弄:

  • 使用哪种聚类算法:有些更快,有些更准确。有些是确定性的,有些不是。
  • 多长时间运行一次聚类算法:运行越少越快,运行越多准确。
  • 集群的大小:大多数集群算法允许您对集群的大小进行一些输入。您允许的集群越大,输出越快,但准确度越低。

所以这将是一场速度与准确性的博弈,但至少通过这种方式,您将能够牺牲一些准确性来获得一些速度提升 - 以您目前的方法,您无能为力真正调整。

【讨论】:

    【解决方案2】:

    看看this question。您可以将对象划分为网格,并利用可以将许多遥远的对象视为单个对象的事实进行良好的近似。一个细胞的质量等于它所包含的物体的质量之和。一个细胞的质心可以被视为细胞本身的中心,或者更准确地说是它所包含的对象的barycenter。在平均情况下,我认为这会给你 O(n log n) 性能,而不是 O(n2 sup>),因为您仍然需要计算每个 n 个对象上的重力,但每个对象仅单独与附近的对象相互作用。

    假设您使用 r2 = x2 + y2,然后用 F = Gm1m计算力i>2 / r2,您根本不需要执行平方根。如果您确实需要实际距离,可以使用fast inverse square root。你也可以使用fixed-point arithmetic

    【讨论】:

    • 不确定如何避免平方根。
    • 另外我也不推荐定点。与它们一起工作很烦人,而且我预计不会有显着的性能提升。我宁愿研究来自 SSE 的矢量指令,它可以同时处理多个浮点数。
    【解决方案3】:

    您可能想尝试不太精确的平方根版本。您可能不需要完整的双精度。特别是如果您的坐标系的数量级通常相同,那么您可以使用截断的泰勒级数很快地估计平方根运算,而不会放弃太多的效率。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 2015-02-09
      • 2019-03-19
      • 2015-03-12
      • 2012-05-30
      • 1970-01-01
      相关资源
      最近更新 更多