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/ocaml-multicore#543 weaklifetime 測試的平行版本
現在已將
weaklifetime.ml
測試的平行版本新增到測試套件中。 -
ocaml-multicore/ocaml-multicore#546 domain_dls 和 ephetest_par 測試中網域生命週期的涵蓋範圍
額外的測試,以增加
domain_dls.ml
和ephetest_par.ml
的網域生命週期測試涵蓋範圍。 -
ocaml-multicore/ocaml-multicore$#550 惰性效果測試
包含一個測試,以處理具有惰性計算的效果,適用於許多不同的使用案例。
-
ocaml-multicore/ocaml-multicore#557 移除未使用的網域函數
清理
domain.c
和domain.h
中未使用的函數。
生態系統
進行中
-
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 伺服器基準測試的腳本。
-
ocaml-multicore/retro-httpaf-bench#6 將 OCaml 移至 4.12
已更新組建腳本以使用 4.12.0。
-
ocaml-multicore/retro-httpaf-bench#8 使用 hyper 新增 Rust 基準測試
包含 Hyper 基準測試,但限制為單一核心,以符合其他現有的基準測試。
-
ocaml-multicore/retro-httpaf-bench#9 dune 的發行組建、延展請求量、rust 修正並移除 mimalloc
已更新 Dockerfile、README、build_benchmarks.sh 和 run_benchmarks.sh 檔案。
-
ocaml-multicore/retro-httpaf-bench#15 使基準測試更逼真
此 PR 增強了實作,以正確模擬假設的資料庫請求,並且已相應更新效果程式碼。
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#27 將 expect 測試轉換為 MDX
已更新預期測試以使用 MDX 格式,這避免了對 ppx 函式庫的需求。
-
ocaml-multicore/eio#28 盡可能使用 splice 進行複製
已實作 effect Splice 以及 ocaml-uring 的更新和必要的說明文件。
-
ocaml-multicore/eio#29 改善切換中的例外狀況處理
額外的例外狀況檢查,以處理多個執行緒失敗時的情況,以及
Switch.check
和Fibre.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
使用
Mutex
和Condition
的通道實作現在已完成。效能結果顯示在下圖中
-
ocaml-multicore/multicore-opam#53 新增 base-domains 和 base-effects 套件
現在已將
base-domains
和base-effects
opam 檔案新增至 multicore-opam。 -
ocaml-multicore/multicore-opam#54 將所有多核心套件移至唯一版本和 base-domains 相依性
現在的命名慣例是在任何地方都使用
base-effects
和base-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
,並修正以正確計算配置和完成的工作量,可產生以下速度改進:
-
ocaml-bench/sandmark#223 更好的 Floyd Warshall 演算法
對 Floyd Warshall 實作的改進,修正了隨機種子以使其可重複,並改進了模式匹配。
-
ocaml-bench/sandmark#224 矩陣乘法的一些改進
已更新
matrix_multiplication
和matrix_multiplication_multicore
的程式碼,以方便維護,並且僅在加總數值後才寫入結果。
-
ocaml-bench/sandmark#225 更好的多核心 EA 基準測試
現在,演化演算法會在
fittest
中插入一個輪詢點,以改善基準測試結果。
-
ocaml-bench/sandmark#226 改善 mandelbrot6_multicore 的縮放
如以下圖表所示,現在
mandelbrot6_multicore
可以使用parallel_for
很好地縮放。
-
ocaml-bench/sandmark#227 使用高核心數改善 nbody_multicore 基準測試
現在,
energy
函數已使用parallel_for_reduce
進行平行化,以用於較大的核心數。
-
ocaml-bench/sandmark#229 改善 game_of_life 基準測試
現在,熱門函數已內聯,以改善
game_of_life
基準測試,並且我們避免使用隨機數初始化暫時矩陣。
雜項
-
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]
開始,以進行更好的比較。 -
ocurrent/current-bench#121 使用字串表示 Docker CPU 設定。
現在,
OCAML_BENCH_DOCKER_CPU
設定從整數切換為字串,以支援用於平行執行的 CPU 範圍。
OCaml
進行中
-
已發布 Sandmark 基準測試的執行結果,以取得 4.13.0+trunk 的安全點 PR 的效能數據。PR 已準備好合併。
職位公告
-
多核心 OCaml 執行階段系統工程師 OCaml Labs(英國)、Tarides(法國)和 Segfault Systems(印度)
-
基準測試工具工程師 Tarides
感謝社群中所有 OCaml 用戶、開發人員和貢獻者對專案的持續支持。保持安全!
縮寫
- AMD:超微半導體
- API:應用程式介面
- CI:持續整合
- CPU:中央處理器
- CTF:通用追蹤格式
- DLAB:網域本地分配緩衝區
- EA:演化演算法
- GC:垃圾收集器
- GCD:中央調度
- HTTP:超文本傳輸協定
- OPAM:OCaml 套件管理器
- MVP:最小可行產品
- PR:提取請求
- TPS:每秒交易次數
- UI:使用者介面