簡體   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