在物理和化学模拟中计算配对相互作用是常见的还是使用对象?

计算科学 模拟 正则 表现 爪哇 分子力学
2021-11-28 04:20:03

当模拟原子、分子、胶体等时,是否有程序将每个相互作用的统一体定义为 OOP 意义上的对象?

在我自己的情况下,我一直在 Fortran 中模拟胶体分散体中的磁性纳米粒子,但我有许多在代码中与纳米粒子的每个属性无关的阵列。例如,对于 100 个纳米颗粒,我将阵列 r(3,100) 用于 3D 位置,m(3,100) 用于 3D 磁矩,xi(100) 用于吸附分子表面密度等。

我使用 Fortran 77 编译器开始我的代码,所以我没有使用 Fortran 2003 的 TYPE 功能,它允许我将所有这些数组放在同一类型中。

然而,这些时候我一直在使用 Java,所以我想知道是否可以更好地将每个磁性纳米粒子定义为一个对象。所以我也会在纳米粒子类中定义“移动”、“旋转”等方法。我不确定如何计算配对交互本身。我不知道如何将其定义为对象类方法...我想我必须在“控制器”层中进行,而不是在“模型”层中(使用 MVC 范例)。

我只是在制作这个新程序时犹豫不决,因为我怀疑将我的纳米粒子定义为对象会使模拟变得慢很多,无论代码看起来多么漂亮。但是,如果有其他程序以这种方式定义配对交互单元,那么可能会有很好的理由这样做,而且我不会孤单...... :-)

1个回答

问题是内存布局。可以在内存中查看对象,就像包含数据和函数指针的 C 结构一样。如果您使用 OOP,您将在每个对象中拥有 3D 坐标、3D 磁矩和用于操作此数据的函数的指针。例如,如果要计算所有粒子对之间的距离,则必须迭代粒子的所有坐标。为此,您需要遍历对象数组。对于每个对象,您必须获取 3D 坐标并跳过结构的其余部分(即其他数据和最终指向函数的指针)。

对于内存访问至关重要的 HPC,这种使用内存的方式确实效率低下:使用连续内存的效率要高得多。简而言之,您将加载大量未使用的数据,这些数据会严重使用缓存、增加内存带宽使用、禁用硬件预取可能性、禁用自动矢量化等。

此外,使用函数访问对象中的数据可能会增加一些开销并成为自动矢量化的障碍,这是额外的性能损失。

当然,如果您是专家,您会考虑所有这些要点并编写高效的 OO HPC 代码,但通常非 OO 版本的效率要高得多。

如果你真的想做 OO 编程,那么你应该更喜欢包含数组的对象而不是对象数组。