OCaml 多核心 - 2021 年 9 月

歡迎來到 2021 年 9 月的 多核心 OCaml 月度報告! 本月的更新以及先前的更新由我 @ctk21、@kayceesrk 和 @shakthimaan 彙編。 團隊在過去幾個月一直努力完成最後幾個功能,以達到與標準 OCaml 的功能對等。 我們也與核心 OCaml 團隊密切合作,制定了將多核心 OCaml 上游整合至標準 OCaml 的時間表,現在已達成共識:

OCaml 5.0 將通過域 (domain) 支援共享記憶體平行處理,以及通過效果處理器 (effect handler) 支援直接式 (direct-style) 並發(不含語法支援).

新的程式碼將必須經過上游 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_string4 " 

將會是

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_string4)
      | 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#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_ptryoung_end 定義為 char *,導致配置字組的報告產生偏差。將它們更改為 value * 的 PR 已合併。

  • ocaml-multicore/ocaml-multicore#652young_start/end/ptr 指標設為 value

    為了與主幹對齊,Multicore OCaml 中使用的 young_startyoung_endyoung_ptr 已更新為 value *,而不是 char *

反向移植

執行緒安全

效果處理器

  • 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 issueTo reproduceMulticore OCaml build versionDid 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-includedbatteries.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 秒。

    retro-httpaf-bench-16-performance|690x460

基準測試

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#14best-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 中的平行基準測試中移除。

  • ocaml-bench/sandmark#254 停用沙箱

    在設定 Sandmark 建置的本機 _opam 目錄時,現在會將 --disable-sandboxing 選項預設傳遞至 opam。

我們要感謝社群中所有 OCaml 使用者、開發人員和貢獻者對專案的持續支持。請注意安全!

縮寫

  • CI:持續整合
  • CPU:中央處理器
  • GC:垃圾收集器
  • HTTP:超文字傳輸協定
  • IO:輸入/輸出
  • OPAM:OCaml 套件管理員
  • PR:提取請求
  • UI:使用者介面
  • URL:統一資源定位器
  • VS:Visual Studio