n-body 模拟预期性能 barnes hut

问题描述 投票:0回答:2

我首先使用蛮力进行了 2D n 体模拟,但随后按照 http://arborjs.org/docs/barnes-hut 我实现了 Barnes-Hut 近似算法。然而,这并没有给我带来我想要的效果。

例如:

巴恩斯小屋 -> 2000 具尸体;平均帧时间32 毫秒和 5000; 164 毫秒

暴力破解 -> 2000 具尸体;平均帧时间31 毫秒和 5000; 195 毫秒

这些值是渲染关闭时的值。

我是否正确地假设我没有正确实现该算法,因此性能没有得到实质性提高?

Theta 当前设置为 s/d < 0.5. Changing this value to e.g. 1 does increase performance, but it's quite obvious why this isn't preferred.

单线程

我的代码大致如下:

while(!close)
    {
        long newTime = System.currentTimeMillis();
        long frameTime = newTime-currentTime;
        System.out.println(frameTime);
        currentTime = newTime;

        update the bodies
    }

在更新主体的函数中:

first insert all bodies into the quadtree with all its subnodes
for all bodies
    {
        compute the physics using Barnes-Hut which yields a net force per planet (doPhysics(body))
        calculate instantaneous acceleration from net force
        update the instantaneous velocity
    }

barneshut 功能:

doPhysics(body)
{
    if(node is external (contains 1 body) and that body is not itself)
    {
        calculate the force between those two bodies

    }else if(node is internal and s/d < 0.5)
    {
        create a pseudobody at the COM with the nodes total mass
        calculate the force between the body and pseudobody

    }else (if is it internal but s/d >= 0.5)
    {
        (this is where recursion comes in)
        doPhysics on same body but on the NorthEast subnode
        doPhysics on same body but on the NorthWest subnode
        doPhysics on same body but on the SouthEast subnode
        doPhysics on same body but on the SouthWest subnode
    }
}

实际计算力:

calculateforce(body, otherbody)
{
    if(body is not at exactly the same position (avoid division by 0))
    {
        calculate force using newtons law of gravitation in vector form

        add the force to the bodies' net force in this frame
    }
}
java algorithm simulation physics
2个回答
0
投票

您的代码仍然不完整(请阅读SSCCEs),深入调试不完整的代码不是该网站的目的。然而,这就是我接下来的步骤,以找出错误所在(如果有的话):

  • time only 您担心的函数(让我们称之为 barnes_hutt_update());而不是整个更新循环。将其与等效的非 B-H 代码进行比较,而不是与没有 B-H 的整个更新循环进行比较。这将产生更有意义的比较。
  • 您似乎已将 s/d 0.5 硬编码到您的算法中。将其保留为参数,当它设置得更高时,您应该能够注意到加速;如果设置为 0,则性能与简单的非 B-H 实现非常相似。B-H 的加速来自于评估较少的节点(因为远处的节点集中在一起);你知道你要跳过多少个节点吗? 没有跳过节点,没有加速。另一方面,跳过节点会在计算中引入小错误 - 您是否量化了这些错误?
  • 在线查看 B-H 的其他实现。 D3 的 force 布局 在内部使用它,并且非常可读。有多种现有的四叉树实现。如果您自己构建了它们,它们可能不是最佳的(甚至是有缺陷的)。除非您想边做边学,否则最好使用经过测试的库,而不是自己开发。
  • 速度减慢可能是由于四叉树的使用,而不是由于力的添加本身。与 B-H 力近似本身相比,了解构建和更新四叉树需要多长时间会很有用,因为在这种情况下,四叉树是纯粹的开销。 B-H 需要四叉树,但简单的非 B-H 实现不需要。对于少量节点,naive 会更快(但随着添加的节点越来越多,速度会变得越来越慢)。 随着添加越来越多的主体,性能如何扩展?
  • 您是否创建并丢弃了大量的物体?您可以通过使用
  • 内存池使您的算法避免相关的开销(是的,大量新闻+垃圾收集可能会导致速度显着下降)。

0
投票
我认为这是对算法的更清晰的解释

https://jheer.github.io/barnes-hut/

它还有一个基准图表,显示对于该特定实现,BH 变得更高效的截止点是 6k 体,这是有道理的,因为构建四叉树具有朴素解决方案所没有的开销。

这里真正的问题应该是:当增加主体数量时,两种解决方案的性能如何扩展?

© www.soinside.com 2019 - 2024. All rights reserved.