OCaml 多核心 - 2021 年 9 月
歡迎來到 2021 年 9 月的 多核心 OCaml 月度報告! 本月的更新以及先前的更新由我 @ctk21、@kayceesrk 和 @shakthimaan 彙編。 團隊在過去幾個月一直努力完成最後幾個功能,以達到與標準 OCaml 的功能對等。 我們也與核心 OCaml 團隊密切合作,制定了將多核心 OCaml 上游整合至標準 OCaml 的時間表,現在已達成共識:
OCaml 5.0 將通過域 (domain) 支援共享記憶體平行處理,以及通過效果處理器 (effect handler) 支援直接式 (direct-style) 並發(不含語法支援).
- 域機制 允許 OCaml 程式設計師利用現代處理器上可用的多核心平行處理,來加速 OCaml 程式碼。
- 效果處理器允許 OCaml 程式設計師以直接式撰寫高效能的並發程式,而無需像現今使用 Lwt 和 Async 函式庫那樣使用單子 (monadic) 並發。效果處理器也作為一個有用的抽象概念,可以建構其他非本地控制流抽象,例如產生器、輕量級執行緒等。OCaml 將成為第一批支援效果處理器的工業級語言之一。
新的程式碼將必須經過上游 OCaml 貢獻的通常嚴格審查流程,但我們預計將在未來幾個月內推進審查流程。
回顧:什麼是效果處理器?
以下摘自 「將效果處理器改裝到 OCaml 上」
效果處理器為使用者定義的效果提供模組化的基礎。 關鍵概念是將效果操作的定義與其解釋分離,而其解釋由效果處理器給定。例如
effect In_line : in_channel -> string
宣告一個效果
In_line
,它使用in_channel
類型的輸入通道進行參數化,當執行時會傳回一個string
值。 計算可以在不知道In_line
效果如何實作的情況下執行In_line
效果。 此計算可以由處理In_line
的不同處理器封裝。 例如,In_line
可以通過在輸入通道上執行阻塞讀取或通過將其卸載到事件迴路(例如 libuv)來非同步執行讀取,而無需更改計算。由於效果操作與其實作分離,效果處理器能夠實現新的模組化程式設計方法。效果處理器是異常處理器的概括,除了處理的效果之外,處理器還會獲得執行站點的定界延續。此延續可以用於稍後恢復暫停的計算。這使得非本地控制流機制(例如可恢復異常、輕量級執行緒、協程、產生器和非同步 I/O)可以組合地表達。
OCaml 中效果處理器的實作是單次的 —— 也就是說,延續只能恢復一次,並且如果未使用,則必須明確地終止。 此限制使得在存在可變資料結構的情況下,更容易對控制流程進行推理,並且還允許高效能的實作。
您可以在完整論文中閱讀更多關於 OCaml 中效果處理器的資訊。
為什麼 OCaml 5.0 中沒有效果處理器的語法支援?
目前多核心 OCaml 中的效果處理器無法確保 效果安全。也就是說,編譯器不會確保程式執行的所有效果都得到處理。相反地,未處理的效果會在執行時導致例外。由於我們計劃未來擴展 OCaml 以支援效果系統,因此 OCaml 5.0 將不會支援使用效果處理器進行程式設計的語法。相反地,我們通過標準函式庫中的函式公開相同的功能,保留語法決策,直到效果系統完成。基於函式的效果處理器與目前多核心 OCaml 中具語法的版本一樣具有表達力。例如,免語法版本
effect E : string
let comp () =
print_string "0 ";
print_string (perform E);
print_string "3 "
let main () =
try
comp ()
with effect E k ->
print_string "1 ";
continue k "2 ";
print_string “4 "
將會是
type _ eff += E : string eff
let comp () =
print_string "0 ";
print_string (perform E);
print_string "3 "
let main () =
try_with comp ()
{ effc = fun e ->
match e with
| E -> Some (fun k ->
print_string "1 ";
continue k "2 ";
print_string “4 “)
| e -> None }
可以想像編寫一個 ppx 擴展,讓程式設計師可以編寫接近早期版本的程式碼。
今天我應該使用哪個 opam 切換?
4.12+domains
opam 切換具有所有將進入 OCaml 5.0 的功能,包括作為函式的效果處理器。函式所屬的確切模組可能會在 5.0 版本之前變更,但基本形式應保持不變。
4.12+domains+effects
opam 切換將會被保留,但語法不會被上游整合。此切換主要用於試用學術文獻中 OCaml 效果處理器的範例。
若要了解更多關於使用此效果系統進行程式設計的資訊,請參閱 eio 函式庫和最近的演講。在接下來的幾週內,eio
函式庫將移植到 4.12+domains
以使用基於函式的效果處理器,以便為 OCaml 5.0 做好準備。
進入 9 月 21 日的更新
許多增強功能已合併,以提高標準函式庫的執行緒安全性、改進測試套件涵蓋範圍,以及通常的錯誤修復。生態系統專案的文件已更新,以提高可讀性、語法和一致性。sandmark-nightly Web 服務目前正在 Docker 化,以部署用於視覺化和分析基準測試結果。Sandmark 2.0-beta 分支也已發佈,包含 2.0 功能,可用於測試和回饋。
我們要感謝以下人士的貢獻:
- @lingmar (Linnea Ingmar) 報告了 4.12.0+domains 在
caml_shared_try_alloc
處出現分段錯誤。 - @dhil (Daniel Hillerström) 提供了一個修補程式,用於移除編譯器原始碼中的
drop_continuation
。 - @nilsbecker (Nils Becker) 報告了在使用 Task.pool 管理時,在 14 個核心上發生當機。
- @cjen1 (Chris Jensen) 在試用 Eio README 範例時,觀察並使用 ulimit 來修復
Unix.ENOMEM
錯誤。 - @anuragsoni (Anurag Soni) 為
retro-httpaf-bench
貢獻了一個非同步 HTTP 基準測試。
一如既往,多核心 OCaml 的更新會先列出,然後是來自生態系統工具和函式庫的更新。 最後列出 Sandmark-nightly 的進行中工作和 Sandmark 基準測試任務,供您參考。
多核心 OCaml
進行中
執行緒安全
-
ocaml-multicore/ocaml-multicore#632
Str
模組多域安全性PR#635 使
lib-str
在多核心 OCaml 中可以同時執行,並具有網域安全性。 -
ocaml-multicore/ocaml-multicore#636 用於執行緒安全可變性的函式庫建構鎖
針對建立兩個模組的可能性進行公開討論,這些模組適用於簡單、可變狀態的執行緒安全函式庫。
分段錯誤
-
ocaml-multicore/ocaml-multicore#639 GC 中的分段錯誤
正在針對 @lingmar (Linnea Ingmar) 報告的 4.12.0+domains 中在
caml_shared_try_alloc
處引起的分段錯誤進行調查。 -
ocaml-multicore/ocaml-multicore#646 Coq 在建置期間發生分段錯誤
使用多核心 OCaml 執行時,Coq 證明助手會導致分段錯誤,並且已提供新的 tarball 用於測試。
測試套件
-
ocaml-multicore/ocaml-multicore#640 適用於 Windows 的 GitHub 動作
GitHub 動作已更新,可在 Windows 上執行多核心 OCaml 測試套件。
-
ocaml-multicore/ocaml-multicore#641 使多核心測試套件執行器與標準 OCaml 對等
需要檢閱多核心已停用的測試,以查看是否可以重新啟用,並與主幹類似地平行執行它們。
其他
-
ocaml-multicore/ocaml-multicore#637
caml_page_table_lookup
在 ocaml-multicore 中不可用ancien
套件使用Is_in_heap_or_young
巨集,該巨集內部使用caml_page_table_lookup
,而該巨集尚未在多核心 OCaml 中實作。 -
ocaml-multicore/ocaml-multicore#653 移除
drop_continuation
由 @dhil (Daniel Hillerström) 貢獻的 PR,用於移除
drop_continuation
,因為clone_continuation
也已被移除。
已完成
上游
-
ocaml-multicore/ocaml-multicore#631 不要從
caml_alloc
C 函式中的訊號引發非同步例外此 PR 防止從訊號處理器中引發非同步例外,並避免從 C 語言的
caml_alloc_*
呼叫中輪詢等待中的訊號。 -
ocaml-multicore/ocaml-multicore#638 為標準函式庫新增一些注入性註解
為了使用 Multicore OCaml 編譯
stdcompat
,已將注入性註解從 4.12.0 反向移植到stdlib
。 -
ocaml-multicore/ocaml-multicore#642 移除頁表功能殘留的部分
Multicore OCaml 中未使用頁表,因此已移除相關的巨集和函式定義。
-
ocaml-multicore/ocaml-multicore#643
Core_kernel
的小字報告不正確由於
young_ptr
和young_end
定義為char *
,導致配置字組的報告產生偏差。將它們更改為value *
的 PR 已合併。 -
ocaml-multicore/ocaml-multicore#652 將
young_start/end/ptr
指標設為 value為了與主幹對齊,Multicore OCaml 中使用的
young_start
、young_end
和young_ptr
已更新為value *
,而不是char *
。
反向移植
-
ocaml-multicore/ocaml-multicore#573 將主幹的安全點 PR 反向移植到 multicore
安全點實作已反向移植到 Multicore OCaml。
-
ocaml-multicore/ocaml-multicore#644 小修正
此修補程式將已棄用的巨集
Modify
替換為caml_modify
,並在runtime/caml/alloc.h
中新增了對caml_alloc_float_array
的參考。 -
ocaml-multicore/ocaml-multicore#649 整合主幹的所有 EINTR 修復
來自 ocaml/ocaml#9722 的基於 EINTR 訊號的修復已併入 Multicore OCaml 中。
執行緒安全
-
ocaml-multicore/ocaml-multicore#630 使訊號對 Multicore 安全
Multicore OCaml 中的訊號實作已全面檢修,具有清晰且正確的語意。
-
ocaml-multicore/ocaml-multicore#635 使
lib-str
對 domain 安全此 PR 將
str
中全域變數的使用移至執行緒本地儲存。還新增了一個並行執行str
計算的測試案例。
效果處理器
-
ocaml-multicore/ocaml-multicore#650 新增將效果處理器公開為函式所需的原始功能
包含原始功能以促進
4.12+domains
的更新,以便繼續與4.12+domains+effects
的變更一起運作。 -
ocaml-multicore/ocaml-multicore#651 將深層和淺層處理器公開為函式
此 PR 將深層和淺層處理器公開為 Obj 模組中的函式。它還移除了複製延續的能力。
雜項
-
ocaml-multicore/ocaml-multicore#633 使用
no-flat-float-arrays
編譯 4.12.0+domains 時發生錯誤連結器錯誤已在 PR#644 中修正。
-
ocaml-multicore/ocaml-multicore#647 改善 Multicore 的問題範本
Multicore OCaml 的錯誤報告範本已進行改善,新增了
Describe the issue
、To reproduce
、Multicore OCaml build version
、Did you try running it with the debug runtime and heap verificiation ON?
和Backtrace
等章節。
生態系統
進行中
-
ocaml-multicore/domainslib#43
Task.pool
管理中可能存在的錯誤由 @nilsbecker (Nils Becker) 回報,當使用 14 個核心時,在 Task.pool 管理中發生分段錯誤。
-
ocaml-multicore/multicore-opam#59 修復 ocaml-multicore/ocaml-multicore#514 之後的 batteries
使用正確的 src URL 更新
batteries-included
的batteries.3.3.0+multicore
opam 檔案。 -
ocaml-multicore/multicore-opam#60 Multicore domains+effects 語言伺服器無法與 VS Code 運作
使用 Multicore domains+effects 語言伺服器時,VS Code 會顯示
Request textDocument/hover failed
錯誤。 -
ocaml-multicore/eio#81 是否可能進行 IO 優先順序排序?
關於 IO 優先順序排序和共識系統的纖程排程的查詢。
已完成
建置
-
ocaml-multicore/eventlog-tools 使用 ocaml/setup-ocaml@v2
GitHub 工作流程已更新為在
.github/workflows/main.yml
檔案中使用 4.12.x ocaml-compiler 和ocaml/setup-ocaml@v2
。 -
ocaml-multicore/tezos#3 新增 cron 作業並執行測試
已變更 CI Dockerfile 和 GitHub 工作流程,以便定期在 Multicore OCaml 上執行 Tezos 的測試。
-
ocaml-multicore/tezos#4 每日執行 cronjob
GitHub cronjob 現在已排程為每天從頭開始執行 Tezos 建置。
-
ocaml-multicore/retro-httpaf-bench#12 Dockerfile 建置失敗
此問題已不存在,且 Dockerfile 現在也可以在 CI 中順利建置。
-
ocaml-multicore/eio#80 使用 README 範例時發生 ENOMEM
@cjen1 (Chris Jensen) 回報
Unix.ENOMEM
錯誤,導致無法執行下列 README 範例程式碼片段。使用ulimit
並設定較小的記憶體大小可修復此問題。#require "eio_main";; open Eio.Std;; let main ~stdout = Eio.Flow.copy_string "hello World" stdout Eio_main.run @@ fun env -> main ~stdout:(Eio.Stdenv.stdout env) ;;
文件
-
ocaml-multicore/parallel-programming-in-multicore-ocaml#10 為了流程/語法/一致性而編輯
已審閱並更新 Multicore OCaml 中的並行程式設計章節,以確保一致性、語法流程和可讀性。
-
ocaml-multicore/eio#79 初始編輯,以確保一致性、格式和清晰度
Eio 專案中的 README 已更新,以確保一致性、格式和可讀性。
-
ocaml2020-workshop-parallel
的 README 已更新,包含書籍、影片、專案儲存庫和 OCaml Multicore wiki 的參考連結。
基準測試
-
ocaml-multicore/retro-httpaf-bench#15 優化 Go 程式碼
nethttp-go/httpserv.go
Go 基準測試現在使用Write
而不是fmt.Fprintf
,並移除 yield() 以進行優化。 -
ocaml-multicore/retro-httpaf-bench 新增非同步 HTTP 基準測試
@anuragsoni (Anurag Soni) 提供了一個非同步 HTTP 基準測試,該基準測試在 Docker 中以 4 核心 i7-8559 CPU (2.70 GHz) 執行,連線數為 1000 個,並執行 60 秒。
基準測試
Sandmark-nightly
進行中
-
ocaml-bench/sandmark-nightly#10 將 sandmark-nightly 進行 Docker 化
需要將 sandmark-nightly 服務 Docker 化,才能在多部機器上執行。
-
ocaml-bench/sandmark-nightly#11 重構 sandmark-nightly 筆記本
需要重構 sandmark-nightly 筆記本中的程式碼並將其模組化,以便可以將其重新用作函式庫。
-
ocaml-bench/sandmark-nightly#12 需要修正正規化圖表 (具有兩個以上的基準測試)
即使有兩個以上的基準測試,正規化圖表也只產生一個彩色長條群組。與基準線比較時,需要顯示一個以上的彩色圖表。
-
ocaml-bench/sandmark-nightly#13 將夜間執行記錄與結果一起儲存
可以儲存夜間執行記錄,因為它們對於偵錯任何失敗很有用。
-
ocaml-bench/sandmark-nightly#14 將
best-fit
變體新增至循序基準測試sandmark-nightly 執行應該包含 best-fit 配置器,因為它比 next-fit 配置器更好。可以使用下列命令啟用 best-fit 配置器
$ OCAMLRUNPARAM="a=2" ./a.out
-
ocaml-bench/sandmark-nightly#16 Cubicle 和 Coq 基準測試在最新的 navajo 夜間執行中遺失
由於缺少 Cubicle 和 Coq 基準測試 .bench 檔案,循序基準測試的 UI 無法載入正規化圖表。
-
ocaml-bench/sandmark-nightly#17 Navajo 執行使用的是過時的 Sandmark
需要將部署在 navajo 上的 Sandmark 更新到最新的 Sandmark,並且由於 Makefile 的未提交變更,
git pull
失敗。
Sandmark
進行中
-
ocaml-bench/sandmark#248 Coq 建置失敗
現在可以使用新的 Coq tarball 在 coq-multicore-2021-09-24 測試使用 Multicore OCaml 進行建置。
-
Sandmark
2.0-beta
Sandmark 2.0-beta 分支現在可供測試。它包含新功能,例如套件覆寫選項、將中繼資訊新增至基準測試結果、執行多次反覆運算、基準測試分類、使用者設定,並簡化套件相依性管理。您可以針對下列 OCaml 編譯器變體測試此分支
- 4.12.0+domains
- 4.12.0+stock
- 4.14.0+trunk
$ git clone https://github.com/ocaml-bench/sandmark.github $ cd sandmark $ git checkout 2.0-beta $ make clean; TAG='"run_in_ci"' make run_config_filtered.json $ RUN_CONFIG_JSON=run_config_filtered.json make ocaml-versions/4.12.0+domains.bench $ make clean; TAG='"run_in_ci"' make run_config_filtered.json $ RUN_CONFIG_JSON=run_config_filtered.json make ocaml-versions/4.12.0+stock.bench $ make clean; TAG='"run_in_ci"' make run_config_filtered.json $ RUN_CONFIG_JSON=run_config_filtered.json make ocaml-versions/4.14.0+trunk.bench $ make clean; TAG='"macro_bench"' make multicore_parallel_run_config_filtered.json $ RUN_BENCH_TARGET=run_orunchrt BUILD_BENCH_TARGET=multibench_parallel RUN_CONFIG_JSON=multicore_parallel_run_config_filtered.json make ocaml-versions/4.12.0+domains.bench
請在我們的 GitHub 專案頁面中回報您遇到的任何問題。
已完成
-
ocaml-bench/sandmark#251 更新相依性以使用
4.14.0+trunk
Sandmark master 分支相依性現在已更新為使用 4.14.0+trunk 進行建置。
-
ocaml-bench/sandmark#253 從平行基準測試中移除
Domain.Sync.poll()
Domain.Sync.poll() 函式呼叫現在已棄用,且已從 Sandmark 中的平行基準測試中移除。
-
在設定 Sandmark 建置的本機
_opam
目錄時,現在會將--disable-sandboxing
選項預設傳遞至 opam。
我們要感謝社群中所有 OCaml 使用者、開發人員和貢獻者對專案的持續支持。請注意安全!
縮寫
- CI:持續整合
- CPU:中央處理器
- GC:垃圾收集器
- HTTP:超文字傳輸協定
- IO:輸入/輸出
- OPAM:OCaml 套件管理員
- PR:提取請求
- UI:使用者介面
- URL:統一資源定位器
- VS:Visual Studio