【问题标题】:I need some advice with to find a sufficient algorithm for my simulation我需要一些建议来为我的模拟找到足够的算法
【发布时间】:2011-10-20 07:41:40
【问题描述】:

我正在做一些粒子粒子的Monte-Carlo simulation。我的代码中有几个瓶颈,但主要的一个是在我进行的一些尝试中,我需要更新 all 粒子属性。代码是用 c++ 编写的,目前我有几个循环来实现:
1.循环存储所有粒子的旧属性并更新新属性。
2. 二维交互循环。
3. 另一个 2D 交互循环(我无法将它与第一个循环结合)。
4.一个循环来存储接受步骤/一个循环来拒绝步骤。

我希望使用交换删除第 4 步,但我找不到这样做的方法。所有粒子都是一个类,它有几个名为propertiesnextPropertiesoldProperties 的元素。您将如何处理?

【问题讨论】:

  • 如果没有看到一些代码,这很难回答。能举出一个简单的例子来说明你的问题吗?
  • 您可以尝试对特定部分进行计时,并查看您的瓶颈到底在哪里。一旦你发现了,发布慢代码将帮助 SO 的优秀人员帮助你找到解决方案。

标签: c++ algorithm scientific-computing


【解决方案1】:

听起来你可以使用double buffering。基本上,您需要维护指向两个粒子对象数组的指针——例如,将它们称为acceptedtrial。在试验开始时,将accepted 数组上的粒子属性复制到trial 数组上的属性,并进行任何您想要的修改。如果试用成功,则只需交换指针,使原来的trial 数组变为accepted,反之亦然。

另外,您说只有 一些 试验涉及昂贵的更新。如果是这样,您可能会对fast variable draggingensemble updating 等技术感兴趣。

【讨论】:

  • 我不知道你的c++技能如何,你知道我是否可以持有指向迭代器的指针吗?
  • 如果你有vector<Foo> v1vector<Foo> v2,那么v1.swap(v2)应该很便宜。
【解决方案2】:

步骤#2 和#3 将是O(N^2),而#1 和#4 是O(N),所以你应该专注于这些。

如果您绝对需要在每对粒子之间进行计算,那么您无能为力。但最有可能的是,相距超过一定距离的粒子彼此之间的影响可以忽略不计,或者您可能只需要处理最近的k 粒子(对于固定的k)。在这种情况下,八叉树(或 kd-tree、aabb 树或类似的东西)是减少成对计算次数的最佳选择。

特别是,您可能想研究Barnes-Hut 方法,该方法用于降低引力计算的复杂性。

【讨论】:

  • 第 3 步是静电的,在许多方面类似于重力。在第 4 步中,我做了很多复制,我认为这很耗时,不过我会看看你的方法。
【解决方案3】:

我认为主要瓶颈是您的 2D 交互。如果您正在进行 N^2 次交互,您可能需要考虑是否可以使用平均场近似,基本上将计算域拆分为单元格,为每次迭代计算每个单元格的平均场,然后只计算与同一细胞中的粒子相互作用,加上周围细胞的平均场校正。

Here您可以阅读有关此优化以及何时相关的更多详细信息

【讨论】:

  • 第一个 N^2 步骤是明智地处理这个单元格。第二个不是(我很确定这是真正的瓶颈)。但是,我需要检查这对于我的目的而言是否可接受。
  • 这取决于您进行第二次 N^2 传递的原因以及传递的目的,然后我们可以为您提供帮助。你能更详细地解释一下这一步吗?
  • 第 3 步是对我系统中的所有带电粒子求和。当有 1000 个时,代码真的很慢。我还使用一种称为 Lekner summation 的方法来处理系统的周期性属性。这种方法迫使我使用地图。
  • 您是否有理由不使用单元格来计算第 3 步?如果你想得到一个误差估计器,你可以增加每个粒子周围的阈值最小单元,其中平均场近似开始起作用,并使用差异来得到你的估计
  • ‎我不使用细胞方法的主要原因是我需要询问我的顾问是否可以。不过这只会在周日发生。
猜你喜欢
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多