在展开的链表上运行大约占代码运行时的40% - 是否有任何明显的优化方法?

rfl*_*500 14 c++ optimization performance

我是一个名为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;
}
Run Code Online (Sandbox Code Playgroud)

此代码的函数和变量的高级概述如下:有一个物理向量的一维数组(分为三个1D数组,每个组件x,y,z用于内存缓存目的atoms::x_spin_array,等)称为'旋转".这些旋转中的每一个都与其他一些旋转相互作用,并且所有交互都存储为一维邻居列表(atoms::neighbour_list_array).每个原子的相关交互列表由listarray两个独立数组中的邻居的起始和结束索引确定.在计算结束时,每个原子自旋具有有效场,该有效场是相互作用的矢量和.

鉴于代码量少,运行时占用的运行时间相当大,我做得最好,但我觉得必须有一种方法可以进一步优化,但作为物理学家而不是计算机科学家,我可能会遗漏一些东西?

Del*_*ore 6

你有一个恒定的乘法流,减去并加上连续的数据.这似乎是SSE的理想用途.如果它的内存带宽有限,那么就改用OpenCL/CUDA.

如果您不熟悉所有低级指令,请尝试使用库.

然后可能会重新调整内部循环可能导致加速.


Mud*_*zvi 0

我觉得以下建议可以帮助您稍微优化代码(即使不能完全优化):

  1. 尽可能使用初始化而不是赋值
  2. 更喜欢预增量而不是后增量以获得更好的速度。(相信我,它确实会带来改变)

除此之外,我认为代码很好。每个 DS 都有一些优点和缺点......你必须忍受它。

快乐编码!