我正在研究一个massive数字处理项目。从一开始我就一直在优化一切,因为我知道这很重要。在进行性能分析时,我的代码几乎 40% 的生命时间都花在一个函数上——二叉树迭代器。
public ScTreeNode GetNodeForState(int rootIndex, float[] inputs)
{
0.2% ScTreeNode node = RootNodes[rootIndex].TreeNode;
24.6% while (node.BranchData != null)
{
0.2% BranchNodeData b = node.BranchData;
0.5% node = b.Child2;
12.8% if (inputs[b.SplitInputIndex] <= b.SplitValue)
0.8% node = b.Child1;
}
0.4% return node;
}
C# 优化专家是否有任何进一步优化的建议?所有比较都是浮动的。我知道理论上这应该不重要,但我使用的是字段而不是属性,因此可以确保优化。这里节省一点点就可以缩短流程几天。
请不要回复说“这些优化在现实世界中并不重要”——因为在这种情况下它们确实重要。 :-)
编辑:我已按照下面的注释将代码更新为现在的代码,并添加到每行代码的性能分析输出中。正如您所看到的,主要杀手是空检查 - 为什么?我尝试在节点上使用布尔标志 IsLeaf 而不是空检查,但该行的性能受到同等影响。
分支节点对象的代码如下:
public sealed class BranchNodeData
{
/// <summary>
/// The index of the data item in the input array on which we need to split
/// </summary>
internal int SplitInputIndex = 0;
/// <summary>
/// The value that we should split on
/// </summary>
internal float SplitValue = 0;
/// <summary>
/// The nodes children
/// </summary>
internal ScTreeNode Child1;
internal ScTreeNode Child2;
}
另一个编辑:这里还有更多的思考......我想知道为什么这条线
BranchNodeData b = node.BranchData;
记录了执行的 0.2%,空比较行记录了 17.7%。我猜这是分支预测失败?虽然该比较被多次命中,并且几乎总是返回 true,但这使得 CPU 很难预测它何时会返回 false。我不太了解 CPU 的低级工作原理,但情况可能是这样吗?