OCaml 多核處理 - 2021 年 5 月

歡迎來到 2021 年 5 月的 多核 OCaml 月報!本月的更新以及先前的更新由 @avsm、@ctk21、@kayceesrk 和 @shakthimaan 整理而成。

首先,我們在 OCaml 編譯器上的所有上游活動,現在都作為 @gasche 開始的全新編譯器開發電子報 #2 的一部分報告。這代表一個小而重要的轉變 - 僅限領域的多核處理已牢牢鎖定在 OCaml 5.0 的上游路線圖上,而整個 OCaml 編譯器團隊一直在協助和貢獻其中,其中 GC 安全點功能是最後一個主要的多核處理先決條件之一(並且即將在 OCaml 4.13 中推出)。

此多核處理電子報現在將著重於讓我們的生態系統為 OCaml 5.0 中僅限領域的多核處理做好準備,以及(尚未正式發布的)效果系統和多核 IO 堆疊的進展情況。本月篇幅較長,請準備好您最喜歡的飲料,讓我們開始吧 :-)

OCaml 多核處理:4.12.0+domains

多核編譯器現在支援其垃圾收集器的 CTF 執行時間追蹤,並且有工具可顯示垃圾收集器事件的 Chrome 追蹤視覺化。在 Sandmark 的現有基準中,進行了一些效能改進(稍後請參閱加速圖),突顯了一些充分利用多核處理的方法。此外,還致力於使用工作竊取雙端佇列將 domainslib 中基於任務的平行處理擴展到 128 個核心/域,使我們更接近 Cilk 樣式的任務平行效能。

與新功能同樣重要的是我們決定做的事。我們已經研究和評估領域本機配置緩衝區 (DLAB) 一段時間了,目的是降低次要 GC 的成本。我們發現產生的效能與我們的預期不符(相較於變更的複雜性),因此我們決定不在 OCaml 5.0 中執行此操作。您可以在DLAB 摘要頁面中找到我們經驗的總結。當活動部件較少時,我們將在 OCaml 5.0 之後再回到此問題。

為 5.0.0 僅限領域做好準備的生態系統變更

由於我們正在為未來幾個月準備包含多核分支的 5.0 分支,因此我們正在加緊準備工作,以確保 OCaml 生態系統已準備就緒。

在 opam-repo 中預設提供多核編譯器

在接下來的幾週內,我們將把多核 4.12.0+domains 和相關套件從其 opam 遠端合併到 ocaml-multicore/multicore-opam 中的主線 opam 儲存庫中。這是為了讓使用變體編譯器更方便,以便開始使用 Domain 測試您自己的套件。

作為此變更的一部分,opam 儲存庫中將提供兩個新的基本套件

  • base-domains:此套件表示目前編譯器具有 Domain 模組。
  • base-effects:此套件表示目前編譯器具有實驗性的效果系統。

透過新增對這些套件的相依性,唯一的有效解決方案將是 4.12.0+domains(直到將包含此模組的 OCaml 5.0)或 4.12.0+effects

這樣做的目的是讓社群套件在 OCaml 5.0 之前更容易發布使用僅限領域平行處理的代码版本,以便我們可以儘早開始遷移和執行緒安全性。我們目前不鼓勵任何人依賴 base-effects,因為它變動性非常高。

此 opam 儲存庫變更尚未推出,但合併後我會在此貼文上評論。

調整 Stdlib 以提高執行緒安全性

在移植第三方程式庫之前,我們必須做的第一件事是讓 Stdlib 為執行緒安全性做好準備。這並不像乍看之下那麼簡單:如果我們採用簡單的方法,只是在每個全域狀態周圍放置一個互斥鎖,我們的循序效能將會降低。因此,我們正在執行更精細的分析和修復,可以在多核 stdlib 頁面上看到。

對於任何希望貢獻的人:在 Stdlib 中搜尋全域狀態,並將其適當分類,然後建立一個使用多個 Domain 執行的測試案例來執行該模組,並提交 PR 至 ocaml-multicore。一般來說,如果您現在看到任何建置失敗或執行時間失敗,我們也會非常感謝您在此處提交問題。您可以在此處(針對 mirage-crypto)和此處(針對 Coqt)看到一些此類問題的良好範例。

將第三方程式庫移植到 Domains

正如我上個月提到的,我們呼籲希望移植程式碼的程式庫和維護人員。我們本月從以下程式庫和應用程式開始

  • Lwt:著名的輕量級執行緒程式庫現在有一個 PR 來新增 Lwt_domains。這是使用 Lwt 的多核核心的第一個簡單(ish)步驟:它讓您可以在另一個 Domain 中透過 detach : ('a -> 'b) -> 'a -> 'b Lwt.t 執行純粹的(非 Lwt)函式。

  • Mirage-Crypto:我們正在調整的下一個程式庫是加密程式庫,因為它也是應該易於平行處理的簡單目標(因為加密函式沒有太多全域狀態)。移植仍在進行中,因為有一些次要的建置失敗,而且 Format 中也有一些 Stdlib 函式尚未執行緒安全,這些函式造成失敗

  • Tezos-Node:我們將一些先前的相依性套用到的較大應用程式是 Tezos-Node,它透過 Lwt、mirage-crypto、Irmin、Cohttp 和許多其他程式庫利用此處的相依性鏈。我們現在已讓它在 4.12.0+domains 下編譯,並且大致通過了測試套件,但只有在相依性和 Stdlib 通過後才會報告顯著結果。

  • Owl:OCaml 最受歡迎的機器學習程式庫在 4.12.0+domains 中出乎意料地運作良好。使用它編寫的一個重要機器學習程式碼庫的實驗發現,在一些錯誤的共用瓶頸出現之前,加速約為 2-4 倍。這相當不錯,因為我們沒有對程式碼庫本身進行任何變更,但請繼續關注未來幾個月隨著我們分析瓶頸而進行的更多改進。

希望這能向你們所有人發出信號,開始在您自己的應用程式中「嘗試」使用 4.12.0+domains,特別是關於了解將其包裝在 Domains 中如何運作並識別全域狀態。您可以閱讀我們方便的關於使用多核 OCaml 進行平行程式設計的教學

我們正在開發一些工具來協助尋找全域狀態,但我們需要一起努力來找出其中一些情況並開始遷移。至關重要的是,我們的相依性鏈中需要一些多樣性 — 如果您有使用 (例如) Async 或原始 Thread 模組的有趣應用程式,並且有一些週期可以與我們合作,請與我或 @kayceesrk 聯繫。

4.12.0+effects

基於效果的eio 程式庫進展順利,介面和設計原理都在存放庫的 README 中保持最新。主要的 IO 後端是ocaml-uring,我們現在正在準備將其單獨發布到 opam 儲存庫,因為它在 Linux 的循序執行時間上也能正常運作(只要您擁有相當新的核心即可。否則核心會崩潰)。我們還有一個Grand Central Dispatch 效果後端,為我們提供完全不同的執行模型來執行我們的效果處理常式抽象。

雖然我們本月不會發布基於效果的 IO 的效能數字,但您可以透過查看retro-httpaf-bench存放庫來了解我們正在執行的測試類型,該存放庫現在有基於效果、基於 uring 和基於 select 的 Web 伺服器的各種排列。我們已向今年夏天即將舉行的 OCaml Workshop 提交演講,如果被接受,將會深入探討我們基於效果的 IO。

如同往常,我們先從 Multicore OCaml 正在進行和已完成的任務開始。接著列出生態系統的改進,然後是 Sandmark 基準測試專案的更新。最後,為了您的參考,我們也會提及上游 OCaml 的工作。如果您已經讀到這裡,並且覺得沒有比開發多核心程式設計運行時更有趣的事情,我們正在英國、法國和印度招募人才 -- 請在文末查看職位公告!

Multicore OCaml

進行中

  • ocaml-multicore/ocaml-multicore#552 為 configure 新增 force_instrumented_runtime 選項

    新增了一個 --enable-force-instrumented-runtime 選項,以便在連結器調用時使用儀器化的運行時以取得事件日誌。

  • ocaml-multicore/ocaml-multicore#553 啟用 flambda 時測試套件失敗

    啟用 flambda 時,b23a416 上有一系列測試失敗,需要進一步調查。

  • ocaml-multicore/ocaml-multicore#555 運行時:CAML_TRACE_VERSION 現在設定為 Multicore 特定的值

    定義一個 CAML_TRACE_VERSION,以區分 Multicore OCaml 和 trunk 的運行時。

  • ocaml-multicore/ocaml-multicore#558 重構 Domain.{spawn/join} 以不使用臨界區

    此 PR 移除了 Domain.wait 以及 Domain.{spawn/join} 中臨界區的使用。

  • ocaml-multicore/ocaml-multicore#559 改善 Multicore GC 統計資訊

    一個草案 PR,用於在使用 OCAMLRUNPARAM=v=0x400 時包含更多 Multicore GC 統計資訊。

已完成

  • ocaml-multicore/ocaml-multicore#508 網域本機配置緩衝區

    目前已捨棄 OCaml Multicore 的網域本機配置緩衝區實作。PR 本身有相關討論,並且這裡有一個 wiki 頁面 here

  • ocaml-multicore/ocaml-multicore#527 將 eventlog 移植到 CTF

    eventlog 實作移植到通用追蹤格式的作業已完成。

    如需關於產生運行時事件的 Chrome 追蹤視覺化效果的簡介,請參閱 eventlog-tools。這個後處理工具將 CTF 追蹤轉換為 Chrome 追蹤格式,允許像這樣的互動式視覺化

OCaml-Multicore-PR-527-Illustration|690x475

生態系統

進行中

  • ocaml-multicore/eventlog-tools#2 新增 pausetimes 工具

    eventlog_pausetimes 工具會取得事件日誌檔案的目錄,並計算平均值、最大暫停時間,以及高達第 99.9 個百分位數的分布。例如

    ocaml-eventlog-pausetimes /home/engil/dev/ocaml-multicore/trace3/caml-426094-* name
    {
      "name": "name",
      "mean_latency": 718617,
      "max_latency": 33839379,
      "distr_latency": [191,250,707,16886,55829,105386,249272,552640,1325621,13312993,26227671]
    }
    
  • domainslib#29 使用 CL 雙端佇列的任務竊取

    使用任務竊取 Chase Lev 雙端佇列在網域之間排程任務的這項持續進行的工作,看起來非常有希望。特別是對於具有 128 個核心的機器。

  • ocaml-multicore/retro-httpaf-bench#10 新增 Eio 基準測試

    為 retro-httpaf-bench 新增一個 Eio 基準測試。這是一項進行中的工作。

  • ocaml-multicore/eio#26 Grand Central Dispatch 後端

    實作 Eio 的 Grand Central Dispatch (GCD) 後端的早期草案 PR。

  • ocsigen/lwt#860 Lwt_domain:Multicore 平行處理的介面

    一項持續進行的工作,目的是引入 Lwt_domain,以使用 Multicore OCaml 的網域對 CPU 核心執行計算。

已完成

retro-httpaf-bench

retro-httpaf-bench 儲存庫包含執行 HTTP 伺服器基準測試的腳本。

eio

eio 函式庫為 Multicore OCaml 提供基於效果的平行 IO 堆疊。

  • ocaml-multicore/eio#18 新增 fibreslib 函式庫

    已將 promise 函式庫重新命名為 fibreslib,以避免與 opam 中現有的套件發生命名衝突,並且 API (waiter 和效果) 已分割到各自的模組中。

  • ocaml-multicore/eio#19 更新至最新的 ocaml-uring

    已更新程式碼和設定檔以使用最新的 ocaml-uring

  • ocaml-multicore/eio#20 新增 Fibreslib.Semaphore

    實作 Fibreslib.Semaphone 模組,此模組對於速率限制非常有用,並且以 OCaml 的 Semaphore.Counting 為基礎。

  • ocaml-multicore/eio#21 新增高階 Eio API

    一個具有來源和接收器介面的新 Eio 函式庫。已使用動機和使用方式更新 README 文件。

  • ocaml-multicore/eio#22 為結構化並行新增切換

    使用追蹤和使用模擬進行測試的文件範例,實作結構化並行。

  • ocaml-multicore/eio#23 將儲存庫重新命名為 eio

    現在已將 OCaml 的基於效果的平行 IO 儲存庫從 eioio 重新命名為 eio

  • ocaml-multicore/eio#24 將 lib_eioio 重新命名為 lib_eunix

    已更新名稱以符合 dune 檔案。

  • ocaml-multicore/eio#25 偵測死結

    如果排程器完成時,主要執行緒繼續執行,現在會引發例外狀況以偵測死結。

  • ocaml-multicore/eio#27 將 expect 測試轉換為 MDX

    已更新預期測試以使用 MDX 格式,這避免了對 ppx 函式庫的需求。

  • ocaml-multicore/eio#28 盡可能使用 splice 進行複製

    已實作 effect Splice 以及 ocaml-uring 的更新和必要的說明文件。

  • ocaml-multicore/eio#29 改善切換中的例外狀況處理

    額外的例外狀況檢查,以處理多個執行緒失敗時的情況,以及 Switch.checkFibre.fork_ignore 的情況。

  • ocaml-multicore/eio#30 新增 eio_main 函式庫以自動選擇後端

    使用 eio_main 根據平台選擇適當的後端 (例如 eunix)。

  • ocaml-multicore/eio#31 新增 Eio.Flow API

    實作一個 Flow 模組,允許雙向流和可關閉的流等組合。

  • ocaml-multicore/eio#32 對網路的初始支援

    Eio 為網路連線提供高階 API,並且已新增 Network 模組。

  • ocaml-multicore/eio#33 在 README 中新增一些設計原理註解

    已更新 README,包含設計註解,並參考關於物件功能模型原則的進一步閱讀資料。

  • ocaml-multicore/eio#34 新增關閉,允許關閉接聽插槽,新增 cstruct_source

    新增 cstruct_source、shutdown 方法以及來源、接收器和檔案描述符類型。

  • ocaml-multicore/eio#35 新增 Switch.on_release 以自動關閉 FD

    我們現在可以將檔案描述符等資源附加到切換,並且這些資源會在切換完成時釋放。

雜項

  • ocaml-multicore/domainslib#23 執行測試:從 run_test 目標中的手動命令移至 dune runtest

    現在使用 dune runtest 命令來執行測試。

  • ocaml-multicore/domainslib#24 從 Domain.Sync.{notify/wait} 移至 Mutex & Condition

    使用 MutexCondition 的通道實作現在已完成。效能結果顯示在下圖中

Domainslib-PR-24|465x500

  • ocaml-multicore/multicore-opam#53 新增 base-domains 和 base-effects 套件

    現在已將 base-domainsbase-effects opam 檔案新增至 multicore-opam。

  • ocaml-multicore/multicore-opam#54 將所有多核心套件移至唯一版本和 base-domains 相依性

    現在的命名慣例是在任何地方都使用 base-effectsbase-domains

基準測試

進行中

  • ocaml-bench/sandmark#230 使用 dune.2.8.1 為 4.13.0+trunk 構建

    這是一個正在進行中的工作,旨在升級 Sandmark 以使用 dune.2.8.1 來構建 4.13.0+trunk 並產生基準測試。您可以使用以下方式進行相同的測試:

    TAG='"macro_bench"' make run_config_filtered.json
    RUN_CONFIG_JSON=run_config_filtered.json make ocaml-versions/4.13.0+trunk.bench
    

已完成

Sandmark

效能
  • ocaml-bench/sandmark#221 修正解壓縮工作迭代次數

    使用 parallel_for、簡化 data_to_compress 以使用 String.init,並修正以正確計算配置和完成的工作量,可產生以下速度改進:

PR-221-Time |690x184 PR-221-Speedup |690x184

  • ocaml-bench/sandmark#223 更好的 Floyd Warshall 演算法

    對 Floyd Warshall 實作的改進,修正了隨機種子以使其可重複,並改進了模式匹配。

Sandmark-PR-223-Time|690x184 Sandmark-PR-223-Speedup|690x184 Sandmark-PR-223-Minor-Collections|690x185

  • ocaml-bench/sandmark#224 矩陣乘法的一些改進

    已更新 matrix_multiplicationmatrix_multiplication_multicore 的程式碼,以方便維護,並且僅在加總數值後才寫入結果。

Sandmark-PR-224-Time|690x184 Sandmark-PR-224-Speedup|690x184

  • ocaml-bench/sandmark#225 更好的多核心 EA 基準測試

    現在,演化演算法會在 fittest 中插入一個輪詢點,以改善基準測試結果。

Sandmark-PR-225-Time|690x184 Sandmark-PR-225-Speedup|690x184

  • ocaml-bench/sandmark#226 改善 mandelbrot6_multicore 的縮放

    如以下圖表所示,現在 mandelbrot6_multicore 可以使用 parallel_for 很好地縮放。

Sandmark-PR-226-Time|690x184 Sandmark-PR-226-Speedup|690x184 Sandmark-PR-226-Minor-Collections|690x184

  • ocaml-bench/sandmark#227 使用高核心數改善 nbody_multicore 基準測試

    現在,energy 函數已使用 parallel_for_reduce 進行平行化,以用於較大的核心數。

Sandmark-PR-227-Time|690x184 Sandmark-PR-227-Speedup|690x184

  • ocaml-bench/sandmark#229 改善 game_of_life 基準測試

    現在,熱門函數已內聯,以改善 game_of_life 基準測試,並且我們避免使用隨機數初始化暫時矩陣。

Sandmark-PR-229-Time|690x184 Sandmark-PR-229-Speedup|690x184

雜項
  • ocaml-bench/sandmark#215 從 treiber_stack.ml 中移除 Gc.promote_to

    4.12+domains 和 4.12+domains+effects 分支已從執行階段移除 Gc.promote_to

  • ocaml-bench/sandmark#216 為 4.12.0+stock、4.12.0+domains、4.12.0+domains+effects 新增配置

    現在,Sandmark 中已包含 4.12.0+stock、4.12.0+domains 和 4.12.0+domains+effects 的 ocaml 版本設定檔。

  • ocaml-bench/sandmark#220 嘗試改善 OCAMLRUNPARAM 文件

    README 已更新,其中包含有關執行基準測試時使用 OCAMLRUNPARAM 配置的更多文件。

  • ocaml-bench/sandmark#222 棄用 4.06.1 和 4.10.0 並升級到 4.12.0

    已移除 4.06.1 和 4.10.0 的 ocaml 版本,並且已更新 CI 以使用 4.12.0 作為預設版本。

current-bench

  • ocurrent/current-bench#103 能夠在 UI 上設定從 0 開始的比例

    現在,圖表的原點從 y 軸的 [0, y_max+delta] 開始,以進行更好的比較。

    current-bench frontend fix 0 baseline

  • ocurrent/current-bench#121 使用字串表示 Docker CPU 設定。

    現在,OCAML_BENCH_DOCKER_CPU 設定從整數切換為字串,以支援用於平行執行的 CPU 範圍。

OCaml

進行中

  • ocaml/ocaml#10039 安全點

    已發布 Sandmark 基準測試的執行結果,以取得 4.13.0+trunk 的安全點 PR 的效能數據。PR 已準備好合併。

職位公告

感謝社群中所有 OCaml 用戶、開發人員和貢獻者對專案的持續支持。保持安全!

縮寫

  • AMD:超微半導體
  • API:應用程式介面
  • CI:持續整合
  • CPU:中央處理器
  • CTF:通用追蹤格式
  • DLAB:網域本地分配緩衝區
  • EA:演化演算法
  • GC:垃圾收集器
  • GCD:中央調度
  • HTTP:超文本傳輸協定
  • OPAM:OCaml 套件管理器
  • MVP:最小可行產品
  • PR:提取請求
  • TPS:每秒交易次數
  • UI:使用者介面