日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里程序员工作小技巧 | 理解CPU分支预测,提高代码效率

發布時間:2024/8/23 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里程序员工作小技巧 | 理解CPU分支预测,提高代码效率 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

技術傳播的價值,不僅僅體現在通過商業化產品和開源項目來縮短我們構建應用的路徑,加速業務的上線速率,也會體現在優秀程序員在工作效率提升、產品性能優化和用戶體驗改善等小技巧方面的分享,以提高我們的工作能力。

從本期開始,我們將邀請來自阿里巴巴各個技術團隊的程序員,涵蓋中間件、前端、移動開發、大數據和人工智能等多個技術領域,分享他們在工作中的小技巧, 內容力求簡短、實用和可操作。

第一期的分享嘉賓,是來自阿里巴巴中間件技術團隊的程序員 - 斷嶺,他是阿里微服務開源項目 Dubbo 的項目組成員,也是Java線上診斷開源項目 Arthas 的負責人。

第一期:理解CPU分支預測,提高代碼效率

一、基礎概念:

  • Dubbo: 是一款高性能、輕量級的開源Java RPC框架,提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動注冊和發現;
  • ChannelEventRunnable: Dubbo 里所有網絡事件的回調接口;
  • JMH:即Java Microbenchmark Harness,是專門用于代碼微基準測試的工具套件。在性能優化的過程中,可以使用JMH對優化的結果進行量化的分析。
  • 二、需求緣起:

    在Stack Overflow上有一個非常著名的問題:為什么處理有序數組要比非有序數組快?從問題的結論來看,是分支預測對代碼運行效率的提升起到了非常重要的作用。

    現今的CPU是都支持分支預測(branch prediction)和指令流水線(instruction pipeline),這倆的結合可以極大的提高CPU的工作效率,從而提高代碼執行效率。但這僅適用于簡單的if跳轉,但對于Switch跳轉,CPU則沒有太好的解決辦法,因為Switch本質上是據索引,是從地址數組里取地址再跳轉。

    三、思考和方案假設:

    要提高代碼執行效率,一個重要的實現原則就是盡量避免CPU把流水線清空,從Stack Overflow上的討論結果來看,通過提高分支預測的成功率,是可以降低CPU對流水線清空的概率。那么,除了在硬件層面,是否可以考慮代碼層面幫CPU把判斷提前,來提高代碼執行效率呢?

    四、方案驗證:

    在Dubbo的ChannelEventRunnable里有一個Switch來判斷channel state。當一個channel建立起來之后,超過99.9%的情況,它的state都是ChannelState.RECEIVED,我們可以考慮,把這個判斷提前。

    以下通過JMH來驗證,把判斷提前后是否就可以提高代碼執行效率。

    率。

    public class TestBenchMarks { public enum ChannelState {CONNECTED, DISCONNECTED, SENT, RECEIVED, CAUGHT }@State(Scope.Benchmark) public static class ExecutionPlan {@Param({ "1000000" })public int size;public ChannelState[] states = null;@Setuppublic void setUp() {ChannelState[] values = ChannelState.values();states = new ChannelState[size];Random random = new Random(new Date().getTime());for (int i = 0; i < size; i++) {int nextInt = random.nextInt(1000000);if (nextInt > 100) {states[i] = ChannelState.RECEIVED;} else {states[i] = values[nextInt % values.length];}}} }@Fork(value = 5) @Benchmark @BenchmarkMode(Mode.Throughput) public void benchSiwtch(ExecutionPlan plan, Blackhole bh) {int result = 0;for (int i = 0; i < plan.size; ++i) {switch (plan.states[i]) {case CONNECTED:result += ChannelState.CONNECTED.ordinal();break;case DISCONNECTED:result += ChannelState.DISCONNECTED.ordinal();break;case SENT:result += ChannelState.SENT.ordinal();break;case RECEIVED:result += ChannelState.RECEIVED.ordinal();break;case CAUGHT:result += ChannelState.CAUGHT.ordinal();break;}}bh.consume(result); }@Fork(value = 5) @Benchmark @BenchmarkMode(Mode.Throughput) public void benchIfAndSwitch(ExecutionPlan plan, Blackhole bh) {int result = 0;for (int i = 0; i < plan.size; ++i) {ChannelState state = plan.states[i];if (state == ChannelState.RECEIVED) {result += ChannelState.RECEIVED.ordinal();} else {switch (state) {case CONNECTED:result += ChannelState.CONNECTED.ordinal();break;case SENT:result += ChannelState.SENT.ordinal();break;case DISCONNECTED:result += ChannelState.DISCONNECTED.ordinal();break;case CAUGHT:result += ChannelState.CAUGHT.ordinal();break;}}}bh.consume(result); }}

    驗證說明:

    • benchSiwtch里是純Switch判斷
    • benchIfAndSwitch 里用一個if提前判斷state是否ChannelState.RECEIVED

    Benchmark結果是:

    Result "io.github.hengyunabc.jmh.TestBenchMarks.benchSiwtch": 576.745 ±(99.9%) 6.806 ops/s [Average] (min, avg, max) = (490.348, 576.745, 618.360), stdev = 20.066 CI (99.9%): [569.939, 583.550](assumes normal distribution) Run complete. Total time: 00:06:48Benchmark (size) Mode Cnt Score Error Units TestBenchMarks.benchIfAndSwitch 1000000 thrpt 100 1535.867 ± 61.212 ops/s TestBenchMarks.benchSiwtch 1000000 thrpt 100 576.745 ± 6.806 ops/s

    可以看到,提前if判斷提高了近3倍的代碼效率,這種技巧可以放在性能要求嚴格的地方。

    五、總結:

    • Switch對于CPU來說難以做分支預測;
    • 某些Switch條件如果概率比較高,可以在代碼層設置提前if判斷,充分利用CPU的分支預測機制;

    ?

    原文鏈接
    本文為云棲社區原創內容,未經允許不得轉載。

    總結

    以上是生活随笔為你收集整理的阿里程序员工作小技巧 | 理解CPU分支预测,提高代码效率的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。