我正在做一个庞大的数字运算项目。从一开始我就一直在优化一切,因为我知道这很重要。进行性能分析时,我的代码几乎 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 的低级工作不是很了解,但这可能是这种情况吗?