提问人:Carlos Andrés del Valle 提问时间:5/15/2021 更新时间:5/15/2021 访问量:213
嵌套 for 循环和 Verlet 列表优化 C++
Nested for loops and Verlet lists optimization C++
问:
我正在用 C++ 模拟分子动力学。我的代码的主要结构如下
particle Molecule[N];
collider Newton;
//initialization of the molecules
for(t=0; t<=tmax; t+=dt){
for(int i=0; I<N; i++)Newton.MovePosition(Molecule[i]);
Newton.CalculateForces(Molecule);
for(int i=0; I<N; i++)Newton.MoveVelocity(Molecule[i])
for(int i=0; I<N; i++)Newton.MovePosition(Molecule[i]);
.
.
.
}
其中,碰撞器类是粒子类的友元,知道每个粒子的位置、速度等。这些粒子与正常的 Lenard Jhones 电位相互作用。在计算力中,我有这样的东西
for(int i=0; i<N; i++)
for(int j=i+1;j<N; j++ )
Molecule[i].F=......
我基本上是在计算其他每个分子对分子 i 施加的力。 我遇到的问题是这个程序效率非常低。我有 2 个嵌套的 for 循环。计算力和积分算法中的力的那个。我想优化这段代码,因为有 25 个粒子和 10^5 次迭代,运行需要很长时间,对于模拟,我想做,我必须至少有 10^3 个分子和 10^5 次迭代。 我尝试了以下方法:
- 我尝试使用并行 for 并行化 for 循环 #omp 并且工作速度比串行版本慢。
- 我读过 Verlet 列表,基本上,粒子不会与所有粒子相互作用,而只会与它们的邻居相互作用。这意味着力计算嵌套循环的大小要小得多。这样做的问题在于,要完成列表,您必须遍历所有粒子,并以某种方式告诉每个粒子是它的邻居。然后循环访问该邻居数组。我一直在思考如何以有效的方式做到这一点,但我还没有想出答案。
- 为了降低 Verlet 列表实现的计算成本,我发现了一种叫做跳过列表的东西,这使得在列表中搜索某些内容成为 O(ln(N)) 操作而不是 O(N)。但实际上,我不太了解它是如何工作的,也不知道如何集成到 Verlet 列表问题中。
- 过去,我做过空间并行化,每个内核对空间中的某个区域进行计算。这样做的问题是它与 Verlet 列表不兼容,我读过 Verlet 列表更好。
- 由于移动位置和速度的运算类似于 V+=Fdt常数,我认为一些约简算法会有所帮助,但我对约简算法一无所知,因此有所帮助。
- 最后,我认为也许在 c++ 17 或 20 中,算法库中可能有一些东西可以提供帮助,但我对算法知之甚少,所以我花了很长时间来阅读文档并确定它的有用之处。到目前为止,我已经开始添加带有向量而不是数组的 for auto。此外,我还有一个小库,允许我将变量定义为 3D 向量并进行正常的向量运算。
因此,我被困在一个位置上,我对编程的了解不够,不知道该做什么,以及我发现的解决方案在哪里遇到了与我现在相同的问题。 所以,如果有人可以帮助我提供关于如何集成所有这些东西的建议,或者如何优化我的代码,或者如果它知道一个特殊的数据结构或算法可以帮助我,我真的很感激你的帮助。 目标是使单个时间步长的积分算法至少为 O(N)。 谢谢。
答: 暂无答案
评论