OCaml 多核心 - 2021 年 6 月
歡迎來到 2021 年 6 月的 Multicore OCaml 月度報告!本月的更新以及先前的更新由 @avsm、@ctk21、@kayceesrk 和 @shakthimaan 共同編撰。
我們的總體目標仍然保持在軌道上,以便在夏季為 OCaml 5.0 多核心僅限網域的平行處理生成預覽樹。
4.12.0+網域的生態系統相容性
在五月份的更新中,我提到我們現在的重點是調整生態系統以與多核心良好協同運作,而且我很高興地報告這方面的進展非常順利。
-
4.12.0+網域的多核心編譯器變體已經合併到主線 opam-repo 中,所以您現在可以直接使用
opam switch 4.12.0+domains
。base-domains
套件也可用於將您的 opam 專案標記為需要Domains
模組,所以您現在甚至可以將您早期支援多核心的函式庫發佈到主線 opam 儲存庫中。 -
OCaml 標準函式庫已透過多個網域(wiki、issue、修復)安全地用於平行處理;尤其是
Format
和Random
模組。這些模組是我們在使用多個網域執行現有 OCaml 程式碼時發現的不相容性的主要來源。
-
Domain
模組的介面已簡化,其中移除了critical_section
、wait
、notify
,這使得執行階段顯著簡化。GC C-API 介面現已實作,這表示 Jane Street 的Base
、Core
和Async
現在可以在4.12+domains
上編譯,而無需修改;例如,opam install patdiff
可以在4.12+domains
切換器上直接運作! -
Domainslib 0.3.0 已發布,其中包含多項改進,包括用於任務分配的工作竊取雙端佇列。讀取網域本機變數的效能也已透過基本型別和 O(1) 查找來改善。關於
Multicore OCaml 中的平行處理
的章節已更新,以反映 Domainslib 的最新開發。
這表示大型應用程式堆疊現在應該可以使用 4.12.0+網域順利編譯(例如 Tezos 節點和 patdiff 等應用程式會運用 opam 中的大量相依性樹)。如果您確實發現不相容性,請務必在儲存庫上回報。
4.12.0+網域+效果
我們的大部分重點都放在使僅限網域的樹狀結構 (用於 OCaml 5.0) 達到最佳速度,但我們也一直在推進直接樣式的基於效果的 IO 堆疊。
- Linux Io_uring 的
uring
繫結現在可以在 opam 儲存庫中取得,因此您也可以在循序 OCaml 上試用。一個不錯的小專案是為現有的 Async 或 Lwt 引擎新增 uring 後端,如果有人想要嘗試做出重大貢獻。 - 現在
eio
函式庫 對於檔案系統和網路而言都相當好用。我們已向 OCaml 工作坊提交一份演講,以更詳細地深入探討其內部原理,因此如果獲得接納,請在未來幾個月內留意。此處的主要變更在於效能改進,而 HTTP 堆疊與 (例如)rust-hyper
相當具競爭力。
我們很快也會有這個樹狀結構的變體,它將移除自訂效果語法,並將纖程(執行階段組件)實作為 Obj
函式。這將進一步提高生態系統相容性,並允許我們建置直接樣式的 OCaml 函式庫,這些函式庫在內部使用纖程來提供並行處理,但不會在其介面中公開任何效果的使用。
基準測試和效能
我們一直很渴望獲得更多能運用多核心功能的基準測試;如果您想要試用多核心並協助撰寫基準測試,wiki 上有一些建議。我們有一個私有伺服器,它使用 Jupyter Notebook 執行 Sandmark 每夜基準測試管線,我們可以將存取權授予任何提交基準測試的人。我們將繼續測試 Sandmark 與 current-bench 的整合,以更好地與 GitHub PR 整合。
一如既往,多核心 OCaml 正在進行和已完成的任務會先列出,然後是來自生態系統及其相關函式庫的更新。接著會提及 Sandmark 基準測試和每夜建置作業。最後,會提供上游 OCaml 安全點 PR 的狀態供您參考。
多核心 OCaml
正在進行
-
ocaml-multicore/ocaml-multicore#573 將主幹安全點 PR 向後移植到多核心
從 ocaml/ocaml 將安全點 PR 向後移植到多核心 OCaml 的進行中工作。
-
ocaml-multicore/ocaml-multicore#584 將訊號處理現代化
將多核心 OCaml 訊號實作更接近上游 OCaml 的修補程式。
-
ocaml-multicore/ocaml-multicore#598 不要將訊號傳遞給已封鎖訊號的執行緒
一個草稿 PR,不會將訊號傳遞給處於封鎖狀態的執行緒。必須處理無系統執行緒案例。
-
ocaml-multicore/ocaml-multicore#600 在標頭中公開更多 GC 變數
caml_young_start
、caml_young_limit
和caml_minor_heap_wsz
變數已在執行階段中定義。 -
ocaml-multicore/ocaml-multicore#601 網域更好的參與者
現在已移除 STW 訊號的疊代
0(Max_domains)
和網域建立的0(n_running_domains)
。 -
ocaml-multicore/ocaml-multicore#603 系統執行緒刻度執行緒
將刻度執行緒移植到多核心 OCaml 的初始草稿 PR。
已完成
增強功能
-
ocaml-multicore/ocaml-multicore#552 新增
force_instrumented_runtime
選項來設定configure
指令碼現在接受新的--enable-force-instrumented-runtime
選項,以方便在連結器調用上使用檢測執行階段以取得事件日誌。 -
ocaml-multicore/ocaml-multicore#558 重構
Domain.{spawn/join}
以不使用臨界區段已移除
Domain.{spawn/join}
中的臨界區段以及Domain.wait
的使用。 -
ocaml-multicore/ocaml-multicore#561 簡化
Domain.Sync
:移除wait
、notify
、critical_section
Domain.Sync
中的重大變更,移除了critical_section
、notify
、wait
、wait_for
和wait_until
。這是為了移除在執行階段中網域到網域的訊息傳遞需求。 -
ocaml-multicore/ocaml-multicore#576 在執行階段中包含 Git 雜湊
現在,Git 雜湊會列印在執行階段中,如下所示
$ ./boot/ocamlrun -version The OCaml runtime, version 4.12.0+multicore Built with git hash 'ae3fb4bb6' on branch 'runtime_version' with tag '<tag unavailable>'
-
ocaml-multicore/ocaml-multicore#579 用於擷取 DLS 根目錄的基本型別
已實作新的基本型別來擷取 DLS,現在是
amd64
上的單一mov
指令。
上游
-
ocaml-multicore/ocaml-multicore#555 執行階段:
CAML_TRACE_VERSION
現在設定為多核心特定的值定義了
CAML_TRACE_VERSION
來區分執行階段的多核心 OCaml 和主幹。 -
ocaml-multicore/ocaml-multicore#581 將我們內嵌的使用方式移至
Caml_inline
我們現在將
Caml_inline
用於執行階段中的所有 C 內嵌,以與上游 OCaml 對齊。 -
ocaml-multicore/ocaml-multicore#589 重新引入
adjust_gc_speed
主幹的
caml_adjust_gc_speed
函式已重新引入多核心 OCaml 執行階段。 -
ocaml-multicore/ocaml-multicore#590 執行階段:在 gc_ctrl 中存根
caml_stat_*
介面在 gc_ctrl.h 中建立
caml_stat_*
存根函式,以引入與主幹中可用的 GC 統計公用程式的相容性層。
修復
-
ocaml-multicore/ocaml-multicore#562 從 DLAB 導入對次要堆積配置程式碼的修復
已移除用於次要堆積配置的 2 倍乘法係數,且來自 config.h 的
Minor_heap_max
限制不再轉換為多核心 OCaml 的位元組大小。 -
ocaml-multicore/ocaml-multicore#593 修復與短暫物件相關的兩個問題
在終止期間簡化短暫物件移交的修補程式。
-
ocaml-multicore/ocaml-multicore#594 修復終結器移交問題
使用
caml_finish_major_cycle
來導致正確移交終結器的主 GC 階段Phase_sweep_and_mark_main
。 -
ocaml-multicore/ocaml-multicore#596 系統執行緒:在初始化執行緒描述元後執行
st_thread_id
即使在初始化執行緒描述元之前,也會設定執行緒 ID,而此 PR 會修正順序。
-
ocaml-multicore/ocaml-multicore#604 修正在
caml_scan_global_young_roots
中未受保護的caml_skiplist_empty
此 PR 引入了
caml_iterate_global_roots
函數,並修正了全域根的鎖定錯誤。
程式碼清理
-
ocaml-multicore/ocaml-multicore#567 簡化部分 minor_gc 程式碼
已簡化 minor_gc.c 程式碼,並清理了
not_alone
變數。 -
ocaml-multicore/ocaml-multicore#580 移除 struct domain
現在
caml_domain_state
是單一的 domain 資訊來源,並移除了struct domain
。struct dom_internal
不再洩漏至執行期環境。 -
ocaml-multicore/ocaml-multicore#583 移除中斷佇列
已移除接收中斷時
struct_interruptor
的鎖定,以及struct interrupt
的使用,簡化了 domain 的實作。
雜項
-
ocaml-multicore/ocaml-multicore#582 在 Random、Hashtbl 和 Filename 中使全域狀態為 domain-local
現在在
Random
、Hashtbl
和Filename
中,Domain-Local 已設定為預設狀態。 -
ocaml-multicore/ocaml-multicore#586 使 Format 中的狀態為 domain-local
現在
Format
中的預設狀態已設定為 Domain-Local。 -
ocaml-multicore/ocaml-multicore#595 實作
caml_alloc_dependent_memory
和caml_free_dependent_memory
Dependent memory 是依賴 GC (和終結器) 進行釋放的堆積記憶體區塊。
caml_alloc_dependent_memory
和caml_free_dependent_memory
已新增至 runtime/memory.c。
生態系統
進行中
-
ocaml-multicore/eventlog-tools#3 使用 ocaml/setup-ocaml@v2
更新了
.github/workflows/main.yml
,以使用 ocaml/setup-ocaml@v2 進行建置。 -
ocaml-multicore/parallel-programming-in-multicore-ocaml#7 新增 Domain-Local Storage 區段
現在 README.md 檔案包含有關 Domain-Local Storage 的章節。
-
ocaml-multicore/eio#26 Grand Central Dispatch 後端
Eio 的 Grand Central Dispatch (GCD) 後端實作正在進行中。
-
ocaml-multicore/domainslib#34 修正
parallel_for_reduce
中的初始值計算一個修補程式,用於修正
parallel_for_reduce
中的初始值,因為該值被計算了多次。 -
ocaml-multicore/domainslib#36 切換至預設的
Random
模組此函式庫已更新為使用預設的
Random
模組,因為它將其狀態儲存在 Domain-Local Storage 中,可以從多個 domain 呼叫。Sandmark 結果如下
-
ocaml-multicore/multicore-opam#56 Base-effects 嚴格依賴 4.12
關於在
base-effects.base/opam
中,OCaml 的嚴格 4.12.0 下限的使用查詢。 -
ocsigen/lwt#860 Lwt_domain: Multicore 並行介面
已將
Lwt_domain
模組移植到 domainslib Task pool,以便使用 Multicore OCaml 的 Domains 在 CPU 核心上執行計算。以下顯示在具有 24 個隔離核心的 Intel Xeon Gold 5120 處理器上獲得的一些基準測試結果
已完成
Ocaml-Uring
ocaml-uring
儲存庫包含適用於 OCaml 的 io_uring
繫結。
-
ocaml-multicore/ocaml-uring#21 新增 accept 呼叫
已將
accept
呼叫新增至 uring,並將unix
函式庫作為依賴項。 -
ocaml-multicore/ocaml-uring#22 新增取消支援
新增了
cancel
方法來請求取消作業。佇列操作和測試也已更新。 -
ocaml-multicore/ocaml-uring#24 整理 cast
已將
Int_val
變更為Long_val
,以移除在 64 位元平台上對符號擴充指令的需求。 -
ocaml-multicore/ocaml-uring#25 修正 test_cancel
新增了具有
queue_depth
引數的with_uring
函數,以處理取消的測試。 -
ocaml-multicore/ocaml-uring#26 新增
openat2
已新增
openat2
方法,可存取所有 Linux 開啟和解析旗標。 -
ocaml-multicore/ocaml-uring#27 微調 C 旗標以獲得更好的效能
已更新 CFLAGS 以提高效能。對於 noop 基準測試,觀察到以下結果
Before: noop 10000 │ 1174227.1170 ns/run│ After: noop 10000 │ 920622.5802 ns/run│
-
ocaml-multicore/ocaml-uring#28 不允許在使用中釋放 ring
ring 在建立時會新增至全域集,並在退出時清除。此外,在配置 slot 之前,會先檢查無效的取消請求。
-
ocaml-multicore/ocaml-uring#29 將 iovec 取代為 cstruct 並清理 C stub
現在
readv
和writev
接受 Cstruct 清單,允許存取 bigarray 的子範圍,並使用多個緩衝區。OOM 錯誤的處理也已改善。 -
ocaml-multicore/ocaml-uring#30 修正 API 中剩餘的 TODO
已將
read
和write
方法分別重新命名為read_fixed
和write_fixed
。已新增Region.to_cstruct
作為建立子 bigarray 的替代方案。如果使用者請求較大的區塊大小,現在會引發例外狀況。 -
ocaml-multicore/ocaml-uring#31 在等待時使用
caml_enter_blocking_section
在等待時使用
caml_enter_blocking_section
和caml_leave_blocking_section
,這允許其他執行緒執行,並且在 Multicore OCaml 的情況下,GC 可以執行。 -
ocaml-multicore/ocaml-uring#32 使用 OCaml 的 C 旗標編譯
uring
在建置 uring 時使用 OCaml C 旗標,並移除未使用的 dune 檔案。
-
ocaml-multicore/ocaml-uring#33 準備發佈
已更新 CHANGES.md、README.md、dune-project 和 uring.opam 檔案,以準備發佈。
-
ocaml-multicore/ocaml-uring#34 將
liburing
轉換為子樹我們現在使用子樹而不是子模組,以便將 ocaml-uring 提交至 opam-repository。
Multicore OCaml 中的平行程式設計
-
ocaml-multicore/parallel-programming-in-multicore-ocaml#5 將
num_domains
變更為num_additional_domains
現在已更新文件和程式碼範例,以使用
num_additional_domains
而不是num_domains
。 -
ocaml-multicore/parallel-programming-in-multicore-ocaml#6 更新有關編譯器版本的最新資訊
已更新 README.md 中的編譯器版本,以使用 4.12 及其變體。
-
ocaml-multicore/parallel-programming-in-multicore-ocaml#8 建議使用者使用預設的 chunk_size 設定
建議在使用
parallel_for
時使用預設的chunk_size
,尤其是在 domain 數量增加時。 -
ocaml-multicore/parallel-programming-in-multicore-ocaml#9 Eventlog 區段更新
現在可以使用
eventlog-tools
函式庫來剖析追蹤檔案,因為 Multicore OCaml 包含來自 trunk 的 CTF 追蹤支援。相關資訊已在 README.md 檔案中更新。
Eio
eio
函式庫為 Multicore OCaml 提供基於 effect 的平行 IO 堆疊。
新增功能
-
ocaml-multicore/eio#41 新增 eio.mli 檔案
已將包含
Generic
、Flow
、Network
和Stdenv
模組的lib_eio/eio.mli
檔案新增至儲存庫。 -
ocaml-multicore/eio#45 新增基本 domain 管理器
此 PR 允許您在另一個 domain 上執行 CPU 密集型工作,並在
traceln
中新增 mutex,以避免輸出重疊。 -
ocaml-multicore/eio#46 新增 Eio.Time 並允許取消睡眠
使用
psq
而不是bheap
函式庫以允許取消。已將Eio.Time
模組新增至lib_eio/eio.ml
。 -
ocaml-multicore/eio#53 新增
Switch.sub_opt
新增了
Switch.sub_opt
的新實作,以允許使用新的 switch 執行函式。此外,已修改Switch.sub
,使其不再是具名引數。 -
ocaml-multicore/eio#54 初始 FS 抽象化
新增了
Dir
模組,以允許檔案系統抽象化以及建立檔案和目錄的功能。在 Linux 上,它使用openat2
和RESOLVE_BENEATH
。 -
ocaml-multicore/eio#56 新增
with_open_in
、with_open_out
和with_open_dir
輔助函數現在
Eio.Dir
模組包含with_open_in
、with_open_out
和with_open_dir
輔助函數。 -
ocaml-multicore/eio#58 新增
Eio_linux.{readv, writev}
已將
Eio_linux.{readv, writev}
函數新增至lib_eio_linux/eio_linux.ml
,它使用新的 OCaml-Uring API。 -
ocaml-multicore/eio#59 新增
Eio_linux.noop
和簡單的基準測試已新增
Eio_linux.noop
實作,用於 Uring 調度的基準測試。 -
ocaml-multicore/eio#61 新增泛型 Enter effect 以簡化排程器
引入了
Enter
effect 來簡化排程器操作,這對 noop 基準測試沒有太大影響,如下所示
改進
-
ocaml-multicore/eio#38 將 Flow.write 重新命名為 Flow.copy
已更新程式碼和文件,以將
Flow.write
重新命名為Flow.copy
,以提高清晰度。 -
ocaml-multicore/eio#36 使用 uring 進行 accept
現在
enqueue_accept
函數使用Uring.accept
以及effect Accept
。 -
針對
Eunix.free
進行最佳化,並使用Uring.peek
處理完成的事件,以獲得更好的效能結果。 -
ocaml-multicore/eio#48 簡化
Suspend
操作已透過將舊的
Await
和Yield
effect 替換為 Eio 中的程式碼,簡化了Suspend
effect。 -
ocaml-multicore/eio#52 將 Linux 支援拆分到
eio_linux
函式庫現在
eunix
具有不同後端共用的通用程式碼,而eio_linux
提供 Linux io-uring 後端。已更新測試和文件以反映變更。 -
ocaml-multicore/eio#57 使用回溯重新引發例外狀況
新增了當 switch 捕捉到例外狀況時儲存回溯參考的支援。當您想要稍後重新引發例外狀況時,這非常有用。
-
ocaml-multicore/eio#60 簡化完成的處理
此 PR 在
type io_job
中新增了Job
和Job_no_cancel
,並加入額外的Log.debug
訊息。
清理
-
ocaml-multicore/eio#42 將 fibreslib 合併至 eio
Fibreslib
的程式碼現在已合併至eio
。您現在需要開啟Eio.Std
而不是開啟Fibreslib
。 -
ocaml-multicore/eio#47 清理網路 API
網路 API 已更新,包含一些變更,例如將
bind
重新命名為listen
、在 Eio API 中以我們自己的型別取代Unix.shutdown_command
,以及以自訂型別取代Unix.sockaddr
。 -
ocaml-multicore/eio#49 移除
Eio.Private.Waiters
和Eio.Private.Switch
Eio.Private.Waiters
和Eio.Private.Switch
模組已移除,等待現在由 Eio 函式庫處理。 -
ocaml-multicore/eio#55 一些 API 和 README 清理
此 PR 包含多項清理和文件變更。README.md 已修改為使用
Eio.Flow.shutdown
而不是Eio.Flow.close
,並新增了一個時間章節。Eio.Network
模組已變更為Eio.Net
。Time.now
和Time.sleep_until
方法已新增至lib_eio/eio.ml
。
文件
-
ocaml-multicore/eio#43 新增關於決定性的設計筆記
README.md 文件已更新,包含一些關於決定性的設計筆記。
-
ocaml-multicore/eio#50 README 改善
更新了 README.md 並新增了
doc/prelude.ml
以用於 MDX。
處理取消
-
ocaml-multicore/eio#39 允許取消接受操作
此 PR 現在支援取消伺服器接受和讀取操作。
-
ocaml-multicore/eio#40 支援取消剩餘的 Uring 操作
現在支援取消
connect
、wait_readable
和await_writable
Uring 操作的請求。 -
ocaml-multicore/eio#44 修正讀取取消測試
ENOENT
值已正確修正為使用 -2,並且已更新取消讀取請求的文件。 -
ocaml-multicore/eio#51 從取消取得
EALREADY
並非錯誤處理
lib_eunix/eunix.ml
中,當操作正在進行中被取消時的EALREADY
情況。
雜項
-
ocaml-multicore/eventlog-tools#2 新增 pausetimes 工具
eventlog-tools
中已新增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] }
-
ocaml-multicore/kcas#9 使用
cpu_relax
回退Domain.Sync.{critical_section, wait_for}
現在已由Domain.Sync.cpu_relax
取代,這與 lockfree 的實作相符。 -
ocaml-multicore/retro-httpaf-bench#10 新增 Eio 基準測試
Eio 基準測試現在已新增至 retro-httpaf-bench GitHub 儲存庫。
-
ocaml-multicore/retro-httpaf-bench#11 在 CI 建置中執行遞迴簽出
已更新
build_image.yml
工作流程,以對 CI 建置執行子模組的遞迴簽出。 -
domainslib#29 使用 Chase Lev 雙向佇列進行任務竊取
用於在網域之間排程任務的任務竊取 Chase Lev 雙向佇列現在已合併,並在具有 128 個 CPU 核心的機器上顯示出有希望的結果。
-
ocaml-multicore/multicore-opam#55 新增 domainslib 的 0.3.0 版本
domainslib.0.3.0
的 opam 檔案已新增至 multicore-opam 儲存庫。
基準測試
進行中
-
ocaml-bench/sandmark-nightly#1 無法變更比較輸入值
當重新計算整個工作簿時,
parallel_nightly.ipynb
筆記本中下拉式選單中的Timestamp
和Variant
欄位會重設。
-
ocaml-bench/sandmark#230 使用 dune.2.8.1 建置 4.13.0+trunk
ocaml-migrate-parsetree.2.2.0
和ppxlib.0.22.2
套件現在可供 4.13.0+trunk 使用,並且我們目前正在將 Sandmark 中的 Irmin Layers 基準測試從使用 Irmin 2.4 移植到 2.6。 -
ocaml-bench/sandmark#231 在夜間筆記本中檢視一組基準測試的結果
一個在 Sandmark Jupyter 筆記本中使用時,可篩選基準測試清單的功能請求。
-
ocaml-bench/sandmark#233 更新 pausetimes_multicore 以符合最新的 Multicore 變更
現在已針對 4.12.0 上游分支和 4.12.0 Multicore 分支更新了暫停時間,以使用新的通用追蹤格式 (CTF)。循序和並行暫停時間結果的產生圖表如下所示
-
ocaml-bench/sandmark#235 更新選定的基準測試,作為基準基準測試的集合
用於比較的基準基準測試應該只能來自 Jupyter 筆記本中使用者選定的基準測試。
-
ocaml-bench/sandmark#236 在 sandmark_nightly 中實作暫停時間支援
循序和並行暫停時間圖表結果需要在 Sandmark 夜間 Jupyter 筆記本中實作。結果與OCaml 的回溯並行性,ICFP 2020 論文中產生的圖 10 和 12 相似。
-
ocaml-bench/sandmark#237 在更大的機器上執行 sandmark_nightly
Sandmark 夜間循序和並行基準測試執行的測試已在 24 核心的機器上完成,我們希望將其部署在 64+ 核心的機器上,以受益於 Domainslib 最近的改進。
-
ocaml-bench/sandmark#241 切換到預設的 Random 模組
目前正在討論是否切換為將
Random.State
用於循序 Minilight、全域根微基準測試和進化演算法。
已完成
-
ocaml-bench/sandmark#232
num_domains
->num_additional_domains
基準測試已更新為現在使用
num_additional_domains
,以與 Domainslib 中的命名一致。 -
ocaml-bench/sandmark#239 將 grammatrix 移植到任務池
Multicore Grammatrix 基準測試現在已移植為使用 Domainslib 任務池。時間和加速圖表如下所示
OCaml
進行中
-
此 PR 目前正在針對 ARM64 和 PowerPC 架構進行測試和評估,特別是套用至
Ipoll
指令的分支鬆弛。
感謝所有 OCaml 社群的使用者、開發人員和貢獻者對專案的持續支持。保持安全!