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+domainsbase-domains 套件也可用於將您的 opam 專案標記為需要 Domains 模組,所以您現在甚至可以將您早期支援多核心的函式庫發佈到主線 opam 儲存庫中。

  • OCaml 標準函式庫已透過多個網域(wikiissue修復)安全地用於平行處理;尤其是 FormatRandom 模組。這些模組是我們在使用多個網域執行現有 OCaml 程式碼時發現的不相容性的主要來源。

  • Domain 模組的介面已簡化,其中移除了 critical_sectionwaitnotify,這使得執行階段顯著簡化。GC C-API 介面現已實作,這表示 Jane Street 的 BaseCoreAsync 現在可以在 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#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:移除 waitnotifycritical_section

    Domain.Sync 中的重大變更,移除了 critical_sectionnotifywaitwait_forwait_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#582 在 Random、Hashtbl 和 Filename 中使全域狀態為 domain-local

    現在在 RandomHashtblFilename 中,Domain-Local 已設定為預設狀態。

  • ocaml-multicore/ocaml-multicore#586 使 Format 中的狀態為 domain-local

    現在 Format 中的預設狀態已設定為 Domain-Local。

  • ocaml-multicore/ocaml-multicore#595 實作 caml_alloc_dependent_memorycaml_free_dependent_memory

    Dependent memory 是依賴 GC (和終結器) 進行釋放的堆積記憶體區塊。caml_alloc_dependent_memorycaml_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 結果如下

Domainslib-PR-36-Results|690x383

  • 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 處理器上獲得的一些基準測試結果

    Lwt-PR-860-Speedup|429x371

已完成

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

    現在 readvwritev 接受 Cstruct 清單,允許存取 bigarray 的子範圍,並使用多個緩衝區。OOM 錯誤的處理也已改善。

  • ocaml-multicore/ocaml-uring#30 修正 API 中剩餘的 TODO

    已將 readwrite 方法分別重新命名為 read_fixedwrite_fixed。已新增 Region.to_cstruct 作為建立子 bigarray 的替代方案。如果使用者請求較大的區塊大小,現在會引發例外狀況。

  • ocaml-multicore/ocaml-uring#31 在等待時使用 caml_enter_blocking_section

    在等待時使用 caml_enter_blocking_sectioncaml_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#34liburing 轉換為子樹

    我們現在使用子樹而不是子模組,以便將 ocaml-uring 提交至 opam-repository。

Multicore OCaml 中的平行程式設計

Eio

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

新增功能
  • ocaml-multicore/eio#41 新增 eio.mli 檔案

    已將包含 GenericFlowNetworkStdenv 模組的 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 上,它使用 openat2RESOLVE_BENEATH

  • ocaml-multicore/eio#56 新增 with_open_inwith_open_outwith_open_dir 輔助函數

    現在 Eio.Dir 模組包含 with_open_inwith_open_outwith_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 基準測試沒有太大影響,如下所示

Eio-PR-61-Benchmark|690x387

改進
  • ocaml-multicore/eio#38 將 Flow.write 重新命名為 Flow.copy

    已更新程式碼和文件,以將 Flow.write 重新命名為 Flow.copy,以提高清晰度。

  • ocaml-multicore/eio#36 使用 uring 進行 accept

    現在 enqueue_accept 函數使用 Uring.accept 以及 effect Accept

  • ocaml-multicore/eio#37 效能改進

    針對 Eunix.free 進行最佳化,並使用 Uring.peek 處理完成的事件,以獲得更好的效能結果。

  • ocaml-multicore/eio#48 簡化 Suspend 操作

    已透過將舊的 AwaitYield 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 中新增了 JobJob_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.WaitersEio.Private.Switch

    Eio.Private.WaitersEio.Private.Switch 模組已移除,等待現在由 Eio 函式庫處理。

  • ocaml-multicore/eio#55 一些 API 和 README 清理

    此 PR 包含多項清理和文件變更。README.md 已修改為使用 Eio.Flow.shutdown 而不是 Eio.Flow.close,並新增了一個時間章節。Eio.Network 模組已變更為 Eio.NetTime.nowTime.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 操作

    現在支援取消 connectwait_readableawait_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 筆記本中下拉式選單中的 TimestampVariant 欄位會重設。

Sandmark-Nightly-1-Issue|690x139

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

    ocaml-migrate-parsetree.2.2.0ppxlib.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)。循序和並行暫停時間結果的產生圖表如下所示

Sandmark-PR-233-Serial-Pausetimes|690x229 Sandmark-PR-233-Parallel-Pausetimes|690x355

  • ocaml-bench/sandmark#235 更新選定的基準測試,作為基準基準測試的集合

    用於比較的基準基準測試應該只能來自 Jupyter 筆記本中使用者選定的基準測試。

Sandmark-Issue-235|383x82

  • 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 任務池。時間和加速圖表如下所示

Sandmark-PR-239-Time|690x357 Sandmark-PR-239-Speedup|690x297

OCaml

進行中

  • ocaml/ocaml#10039 安全點

    此 PR 目前正在針對 ARM64 和 PowerPC 架構進行測試和評估,特別是套用至 Ipoll 指令的分支鬆弛。

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