我正在寻找一些关于如何在我的C++代码中优化几个函数的新想法。我通过一个分析器运行代码,它显示了它们分别占用了20%和40%的时间。这些函数被多次调用,因为它们驻留在一个三重嵌套循环中(无法避免)。
blip3_inner(args...)
(20%的时间)如下:
void PairBlip::blip3_inner(int &i, int &j, int &k, int &e,double g[][2][3],
double gp[][2][3] ,double &blip_ijk, double coef[2])
{
double f[3][2][3];
for (int d=0; d<3; ++d)
for (int a=0; a<2; ++a)
for (int b=0; b<3; ++b)
f[d][a][b] = gp[d][a][b] * blip_ijk - g[d][a][b] * coef[a];
blip3_dump(i,j,k,e,f);
}
blip3_dump(args...)
(40%的时间)是:
void PairBlip::blip3_dump(int &i, int &j, int &k, int &e, double f[][2][3])
{
for (int d=0; d<3; ++d)
{
for (int b=0; b<3; ++b)
{
force_fp[i][d][e+size2b+b*size_grid_3b] += f[d][0][b] + f[d][1][b];
force_fp[j][d][e+size2b+b*size_grid_3b] -= f[d][0][b];
force_fp[k][d][e+size2b+b*size_grid_3b] -= f[d][1][b];
}
}
}
代码使用以下标志进行编译:
-g -std=c++11 -O3 -ffast-math -march=native
代码将用于体系结构的范围,编译器标志的选择实际上取决于最终用户。
整个代码都是用MPI并行化的,所以上面的函数是由单个核计算的。
对于第二个函数,我尝试将堆上声明的force_fp
替换为堆栈上声明的中间变量。虽然它在使用-O
编译时有所改进,但在使用-O3
时,任何好处都会消失。
如果有任何想法,我将不胜感激。
背景
我正在开发机器学习原子间对潜能,以便与https://lammps.sandia.gov/一起工作。代码的结构非常类似于经典的三体势,如Tersoff或Stillinger。上述代码在嵌套的i
、j
、k
循环中被调用,其中i
遍历盒中的所有原子,j
和k
是i
的总体近邻。情况就是这样,没有改进的余地。
<#>更新
我尝试通过扁平blip3_inner()
、g[18]
、gp[18]
来减少许多嵌套循环并改进缓存,但它并没有提高速度。
发布于 2020-03-19 12:31:53
为blip3_dump()
的S偏移表达式引入一个变量:
for (int b=0, e_size2b = e + size2b; b<3; ++b) {
int offset = e_size2b + b * size_grid_3b;
for (int d=0; d<3; ++d) {
force_fp[i][d][offset] += f[d][0][b] + f[d][1][b];
force_fp[j][d][offset] -= f[d][0][b];
force_fp[k][d][offset] -= f[d][1][b];
}
}
请注意,这是如何展开“a
-loop”的--更明显的是使用单独的force_fp[i]
更新。在PairBlip::blip3_inner()
中,展开a
-loop并交换第一个和最后一个索引:
for (int b=0; b<3; ++b)
for (int d=0; d<3; ++d) {
f[d][0][b] = gp[d][0][b] * blip_ijk - g[d][0][b] * coef[0];
f[d][1][b] = gp[d][1][b] * blip_ijk - g[d][1][b] * coef[1];
}
这似乎建议将f[][][]
和关联索引替换为f0
和f1
:
void blip3_inner(int i, int j, int k, int e_size2b,
double g[][2][3], double gp[][2][3],
double &blip_ijk, double coef[2])
{
for (int b=0; b<3; ++b) {
int offset = e_size2b + b * size_grid_3b;
for (int d=0; d<3; ++d) {
double f0 = gp[d][0][b] * blip_ijk - g[d][0][b] * coef[0],
f1 = gp[d][1][b] * blip_ijk - g[d][1][b] * coef[1];
force_fp[i][d][offset] += f0 + f1;
force_fp[j][d][offset] -= f0;
force_fp[k][d][offset] -= f1;
}
}
}
https://codereview.stackexchange.com/questions/239139
复制相似问题