繁体   English   中英

Java for循环中的分支预测

[英]Branch prediction in a java for loop

我在if条件旁边看到了此评论:

// branch prediction favors most often used condition

JavaFX SkinBase类的源代码中。

protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {

    double minX = 0;
    double maxX = 0;
    boolean firstManagedChild = true;
    for (int i = 0; i < children.size(); i++) {
        Node node = children.get(i);
        if (node.isManaged()) {
            final double x = node.getLayoutBounds().getMinX() + node.getLayoutX();
            if (!firstManagedChild) {  // branch prediction favors most often used condition
                minX = Math.min(minX, x);
                maxX = Math.max(maxX, x + node.minWidth(-1));
            } else {
                minX = x;
                maxX = x + node.minWidth(-1);
                firstManagedChild = false;
            }
        }
    }
    double minWidth = maxX - minX;
    return leftInset + minWidth + rightInset;
}

我相信开发人员想解释为什么他写了一个否定if

这种优化真的有用吗?

JavaFX团队的成员非常专注于性能,因此他们肯定知道切换if和else对分支预测没有实质性影响。

我认为这表明重构没有显着的性能改进,因为:

double minX = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE;

for (int i = 0; i < children.size(); i++) {
  Node node = children.get(i);
  if (node.isManaged()) {
    final double x = node.getLayoutBounds().getMinX() + node.getLayoutX();
    minX = Math.min(minX, x);
    maxX = Math.max(maxX, x + node.minWidth(-1));
  }
}

因为分支预测实际上会将if / else变成类似的东西(给定或接受)。


这个提交确认了这个解释,尽管我不确定为什么他们要更改它-可能是因为当isManaged条件从不成立时它具有副作用。

进一步调查,该提交涉及一个错误“在Controls基准测试中性能下降高达50%” (您需要登录才能访问它)。

似乎他们遇到了性能问题,在调查时注意到代码中存在错误(与我上面的示例类似)。 他们修复了该错误,并添加了一条注释以阐明该修复由于分支预测而不会影响性能。

摘录:

[..]在查看代码时,在没有管理任何皮肤孩子的情况下,我注意到一个错误。 在这种情况下,minX / Y和maxX / Y最终将是MAX / MIN_VALUE,我们真正希望它们为零。 因此,此更改集解决了该问题。 在测试中,我发现性能略有提高(〜1 fps),因此我认为此更改不能解决性能问题。 无论如何,代码必须保持原样。

[...]请注意,使用MIN / MAX时有一个错误-那些值不是Float和Double的最大值和最小值(与整数类型对称是有意义的,但不是)指定方式)。 为了对浮点值执行最小/最大运算,您想使用NEGATIVE / POSITIVE_INFINITY值代替以获得所需的结果。

“分支预测偏爱最常用的条件”这句话并没有说明评估条件的值,无论是肯定的还是否定的。 它只是说分支预测可以帮助更频繁使用的条件分支,即循环中的那些。 所以它基本上说,在循环内使用if是可以的。

虽然结论是正确的,但您不必担心s if循环(除非分析器告诉您存在瓶颈,否则您无需担心任何事情),在Java上下文中,该语句本身是毫无意义的。

分支预测是CPU的功能,因此在解释执行中,它与Java级别分支无关,因为它们只是修改解释器的状态(即,将通过其读取下一条指令的指针),但与特定于CPU的指令无关。特定的分支。

HotSpot启动后,情况将完全不同。 如果此代码是热点,那么优化器将应用大量代码转换,从而使大多数关于Java代码将如何执行的假设都是错误的。

一种常见的优化是循环展开 与其有一个代表循环主体的代码块,不如说有一个循环的多个实例相互围绕,并对其特定迭代的不变量进行了优化。 此设置允许完全消除if相关分支,因为完全可以预测,在firstManagedChildtruefalse的第一次转换之后,它将永远不会返回,因此,尽管第一次迭代始终看到它的true值,但是可以优化后续迭代,以将变量始终视为false

因此,在那种情况下,分支预测将再也没有意义,因为if语句的分支可以预先预测,因此没有分支。

这里可以找到有关分支预测出租车的详细文章

回答您的问题-根据我的理解,不可以。 我认为否定“ if”不会有任何影响。 它将优化重复假值的条件,就像重复多个真值一样。

除了现有的答案:

该评论似乎不是“否定如果”的理由(因为无论如何在性能方面都不会有所不同)。 相反,这可能是尝试“优化”代码并避免使用单个if的理由。 可以通过以下方式实现:

protected double computeMinWidth(double height, double topInset, 
    double rightInset, double bottomInset, double leftInset) {

    double minX = 0;
    double maxX = 0;

    // Initialize minX/maxX with the coordinate of the FIRST managed child
    int i = 0;
    for (i = 0; i < children.size(); i++) {
        Node node = children.get(i);
        if (node.isManaged()) {
            final double x = node.getLayoutBounds().getMinX() + node.getLayoutX();
            minX = x;
            maxX = x + node.minWidth(-1);
        }
    }

    // Continue the loop at the last index, updating the
    // minX/maxX with the remaining managed children
    for (; i < children.size(); i++) {
        Node node = children.get(i);
        if (node.isManaged()) {
            final double x = node.getLayoutBounds().getMinX() + node.getLayoutX();

            // Don't have to check whether it's the first managed child here. 
            // Just do the update.

            minX = Math.min(minX, x);
            maxX = Math.max(maxX, x + node.minWidth(-1));
        }
    }
    double minWidth = maxX - minX;
    return leftInset + minWidth + rightInset;
}

注释表明,由于保存了if ,这不会带来任何性能上的好处,因为实际上,由于分支预测,该if实际上将是免费的。

旁注:我认为可能还有其他“微优化”,例如避免使用Math#min(double,double) 但是JavaFX的家伙(希望)知道他们的知识,并且如果情况可能有所不同,可能会这样做)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM