我是名为 vampire ( http://github.com/richard-evans/vampire )的开源科学代码的作者,计算密集型意味着代码性能的任何改进都可以显着增加可以完成的研究量。这段代码的典型运行时间可能是数百个核心小时,所以我一直在寻找提高代码性能关键部分的方法。但是,我有点坚持以下看起来相对无害的代码,它占运行时的 40% 左右:
for (int atom = start_index; atom < end_index; atom++){
register double Hx = 0.0;
register double Hy = 0.0;
register double Hz = 0.0;
const int start = atoms::neighbour_list_start_index[atom];
const int end = atoms::neighbour_list_end_index[atom] + 1;
for (int nn = start; nn < end; nn++){
const int natom = atoms::neighbour_list_array[nn];
const double Jij = atoms::i_exchange_list[atoms::neighbour_interaction_type_array[nn]].Jij;
Hx -= Jij * atoms::x_spin_array[natom];
Hy -= Jij * atoms::y_spin_array[natom];
Hz -= Jij * atoms::z_spin_array[natom];
}
atoms::x_total_spin_field_array[atom] += Hx;
atoms::y_total_spin_field_array[atom] += Hy;
atoms::z_total_spin_field_array[atom] += Hz;
}
此代码的函数和变量的高级概述如下: 有一个物理向量的 1D 数组(为每个分量 x、y、z 拆分为三个 1D 数组,用于内存缓存atoms::x_spin_array
等),称为 'spin '。这些自旋中的每一个都与其他一些自旋交互,并且所有交互都存储为一维邻居列表 ( atoms::neighbour_list_array
)。每个原子的相关相互作用列表由listarray
两个单独数组中邻居的开始和结束索引确定。在计算结束时,每个原子自旋都有一个有效场,它是相互作用的矢量和。
考虑到少量的代码和它占据的运行时间的相当大一部分,我已经做到了最好,但我觉得必须有一种方法可以进一步优化这一点,但作为物理学家而不是计算机科学家,也许我错过了什么?