【发布时间】:2015-07-07 07:47:34
【问题描述】:
编辑 2:程序计算时间减少 16%! 计算见底部
我编写了一个 N 体模拟器,实现了 Barnes-Hut 算法。现在我有一个看起来很无辜的函数,叫做CheckNode。它简单且计算时间不长,但问题是,它被调用了 数百万 次,因此占用了每帧之间的大部分计算时间。
我分析了代码,这个函数负责84.58%的总计算时间,而且这个只有10K个粒子,当我用最多10倍这个的时候,这个函数使用的百分比越来越大。
现在这里是函数,在右侧花费的时间百分比为红色。
现在这里有一些令人担忧的事情,比如一个简单的 if 语句占用了 9.17% 和另一个 if 语句占了超过 20% 的计算时间!有没有可以在这里完成的任何优化,即使是最轻微的优化,也可以乘以数百万次函数调用以使我的程序运行得更快?
编辑:
这是CalculateForceNode函数:
void CalculateForceNode(Body* bi, Node* bj) //bi is being attracted to bj. 15 flops of calculation
{
//vector from the body to the center of mass
double vectorx = bj->CenterOfMassx - bi->posX;
double vectory = bj->CenterOfMassy - bi->posY;
//c^2 = a^2 + b^2 + softener^2
double distSqr = vectorx * vectorx + vectory * vectory + Softener * Softener;
// ivnDistCube = 1/distSqr^(3/2)
double distSixth = distSqr * distSqr * distSqr;
double invDistCube = 1.0f / (sqrt(distSixth));
double Accel = (bj->TotalMass * invDistCube * _GRAV_CONST);
bi->AccelX += vectorx * Accel;
bi->AccelY += vectory * Accel;
}
编辑 2:
优化结果
CheckNode 函数现在占用了总计算时间的 82.03%(在 1 分 37 秒的样本中测量),而之前它占用了 84.58%。
现在逻辑告诉15% 的剩余计算时间,与第二个程序的剩余18% 计算时间相同。所以这些相同的时期(它的代码相同)占用了第一个程序的15%,和第二个程序的18%。让完成此其他代码的时间为x,第一个程序花费了1/0.15 = 6.666x,第二个程序花费了1/0.18 = 5.555x。然后你可以找到5.555x 是6.666x 的分数,它计算为~0.83,因此程序计算时间减少了 (1 - 0.83 = 0.16)16%!
【问题讨论】:
-
在您的 if 语句中,首先检查 HasChildren,避免双重除法并执行 widthSqr
-
我认为您应该向我们展示CalculateForceNode() 的代码,它约为45%。关于 23% 的条件,我认为你应该反转其中一个元素,你应该使用 if(pNode->HasChildren == false || (withSqr / distanceSqr HasChildren == false)
-
另一个问题是..您是否在每个节点上多次调用 checknode,答案是否随时间而变化?如果您保存结果可能会有所帮助,因此您只需计算一次特定节点的校验节点
-
@kieren if (sqrt(x) > 6) 可能变成 if (x > 6 * 6)
-
是的,这实际上用于检查节点功能,我检查
if (widthSqr / distanceSqr < NodeThresholdSq)而不是(width / distance < NodeThreshold)我会在距离上使用 sqrt(),现在我不必这样做,但唯一的另一个sqrt left 我需要它的确切值,而不是关系
标签: c++ optimization