OCaml 多核心 - 2020 年 7 月
歡迎來到 2020 年 7 月的 Multicore OCaml 報告!此更新連同先前的更新,由 @shakthimaan、@kayceesrk 和我共同編撰。無論在上游 OCaml 還是我們的多核心樹中,都有許多進展。
多核心 OCaml
透過領域執行上下文實現執行緒相容性
簡而言之:一旦 #381 合併,dune 將可與多核心 OCaml 搭配運作。
如同我上個月指出的,沒有一個與傳統 OCaml 向後相容的 Thread 模組,是生態系統相容性的一大阻礙。乍看之下,這可能會讓人有些困惑 — 為什麼多核心 OCaml 需要非平行執行緒支援?答案就在多核心 OCaml 中的並發和並行之間的關係。並發是我們如何分割多個計算,使其在重疊的時間段內執行,而並行是我們如何同時在不同的核心上執行它們以獲得更高的效能。許多套件(最值得注意的是 Dune)目前使用 Thread 模組來方便地取得並發性,同時編寫直線程式碼而不使用 monad 抽象。這些用途不需要平行性,但是若要不使用基於執行緒的並發,則很難重寫。
因此,多核心 OCaml 也需要提供一個效能相當好的 Thread 版本的方法。我們嘗試的第一個解決方案(由 @jhw 開始,並由 @engil 在 #342 中繼續)將 Thread 對應到多核心領域,但由於我們的並發上下文(Thread 實例)數量可能遠大於可用的 CPU 數量(Domain 實例),因此在大量執行緒的情況下擴展性不佳。這導致了一場腦力激盪(#357),以找出適用於像 Dune 或 XenServer 堆疊 等大量使用執行緒的應用程式的解決方案。
我們的解決方案引入了一個我們稱之為 #381 中的領域執行上下文的概念,它允許我們將多個系統執行緒對應到 OCaml 領域。一旦該 PR 經過審查並合併到多核心 OCaml 分支中,它將解鎖更多生態系統套件,因為 Dune 建置系統將在未修改的情況下編譯。此後,廣泛 opam 測試的最後一個「重大」障礙是 ocaml-migrate-parsetree,它需要一個小修補程式來支援多核心 OCaml 樹中存在的 effect
關鍵字語法。
領域本機儲存
領域本機儲存 (DLS) (#372) 是一種將 OCaml 值私下附加到領域的簡單方法。在 LU 分解基準測試 的 PR 中展示了使用 DLS 時加速的一個好例子。在這種情況下,基準測試需要大量的隨機數,並且在領域本機平行初始化它們是一個勝利。
另一個例子是演算法的平行實作(最初由 @per_kristian_lehre 在 #336 中提出),它在 #151 中加速良好(對於那些想要檢查基準的人,#155 中有一個循序版本,您可以查看 Sandmark 的網頁介面)。
使用多核心 OCaml 進行平行程式設計(文件)
已提供一份關於使用多核心 OCaml 進行平行程式設計的教學課程。它提供了多核心 OCaml 的簡介,並解釋了 Domains
、Domainslib
和 Channels
的概念。還用範例說明了使用 perf
和 Eventlog
分析 OCaml 程式碼。
此草稿已在 Reddit 以及 HackerNews 上分享,因此您可以在那裡找到更多關於它的討論。
Coq 基準測試
用於 OCaml 的 Sandmark 基準測試套件已成功更新為使用 dune.2.6.0 並為多核心 OCaml 4.10.0 建置。透過此重大升級,我們也已能夠包含 Coq 及其相依性。我們正在努力將更多回歸 Coq 基準測試新增到測試套件中。
上游 OCaml
上游 OCaml 樹在 4.12.0dev 樹中出現了一連串的活動,並進行了變更以準備用於多核心 OCaml。最大的一個是(引述 @xavierleroy 的話)在 ocaml/ocaml#9728 中的傳說中的無頁面壓縮器。這是繼上個月的工作 (#9698) 之後,當編譯器使用 "no-naked-pointers" 選項建置時,消除頁面表的使用,並為平行多核心 OCaml 執行階段整合到未來版本的 OCaml 中鋪平了道路。
我們希望納入 OCaml 4.12 的其他變更之一是標記和清除時垃圾收集器顏色的使用對齊。 #9756 變更使上游執行階段使用我們在 將平行性改裝到 OCaml ICFP 論文中描述的相同方案,並提供了一些額外的改進,您可以在 PR 審閱註解中閱讀。
如果您對完整的變更集感到好奇,您可以看到迄今為止在上游已關閉的所有 多核心先決條件問題。
詳細更新
與先前的更新一樣,多核心 OCaml 更新會先列出,然後是 Sandmark 基準測試專案的增強功能。最後會提及上游 OCaml 正在進行和已完成的更新,以供您參考。
多核心 OCaml
進行中
-
ocaml-multicore/ocaml-multicore#342 使用 Domain 實作執行緒程式庫
這是一個正在進行的工作,以重新定位 @jhwoodyatt 的 Domain 執行緒程式庫實作。
-
ocaml-multicore/ocaml-multicore#357 使用 pthreads 實作系統執行緒
在此實作中引入了領域執行上下文 (DEC),作為使用 pthreads 實作系統執行緒的並發抽象。
-
ocaml-multicore/ocaml-multicore#374 在次要收集時強制主要切片
領域中被封鎖的執行緒在透過
handle_interrupt
服務次要收集器時可能不會推進主要 GC,因此我們需要進行次要收集以排程主要收集切片。
已完成
領域本機狀態
-
Sudha247/ocaml-multicore#1
dls_root
應該在終端 GC 之前刪除全域根的刪除會將物件推送到標記堆疊,因此需要在終端 GC 之前執行最終 GC。
-
ocaml-multicore/ocaml-multicore#372 領域本機儲存
實作領域本機儲存的 RFC 提案 ocaml-multicore#339 已完成並合併到多核心 OCaml 中。
在並行次要 GC 中移除殘留物
-
ocaml-multicore/ocaml-multicore#370 移除 Cloadmut 和 lloadmut
此修補程式已清理
Cloadmut
和Iloadmut
的實作和使用。這簡化了程式碼,並使其更接近於庫存 OCaml。 -
ocaml-multicore/ocaml-multicore#371 領域中斷清理
在
runtime/domain.c
中,已移除struct interruptor* sender
。領域 RPC 函式已在domain.h
中分組在一起,並應用了一致的定義命名。
程式碼清理
-
ocaml-multicore/ocaml-multicore#367 移除一些未使用的 RPC 消費者
領域 RPC 機制已不再使用,並且已被移除。
-
ocaml-multicore/ocaml-multicore#368 移除 read_barrier 和 caml_promote 的無效位元
此 PR 移除了
caml_promote
、ARM 和 AMD 上讀取錯誤的組件,以及讀取錯誤的全域變數。
雜項
-
ocaml-multicore/ocaml-multicore#366 新增事件以記錄閒置領域
新增了
domain/idle_wait
和domain/send_interrupt
事件,以追蹤閒置的網域。以下顯示具有此效果的事件日誌螢幕截圖。
-
ocaml-multicore/ocaml-multicore#369 將 caml_urge_major_slice 分割成 caml_request_minor_gc 和 caml_request_major_slice
caml_urge_major_slices
被分割成caml_request_minor_gc
和caml_request_major_slice
。這減少了次要垃圾回收的總次數,如下圖所示。
-
ocaml-multicore/ocaml-multicore#373 修復當目前目錄名稱包含空格時的 opam pin 指令
使用
opam pin
的-k path
命令列引數來處理包含空白字元的目錄名稱。 -
ocaml-multicore/ocaml-multicore#375 僅在需要時鎖定全域可用列表以採用池
當沒有需要採用的全域池時,會移除配置上的鎖定獲取和釋放。
-
ocaml-multicore/ocaml-multicore#377 將 Travis CI 中運行的環境變數分組
OCAMLRUNPARAM
參數被定義為環境變數的一部分,並使用USE_RUNTIME=d
指令。 -
ocaml/dune#3608 上游 Multicore dune 啟動程式修補程式
此修補程式用於使用次要編譯器方法建置 dune,以解決 ocaml/dune#3548 的問題。
效能評測
進行中
-
ocaml-bench/sandmark#107 新增 Coq 效能評測
Sandmark 升級為使用 Multicore OCaml 4.10.0 的 dune.2.6.0,使得我們能夠安裝 Coq 及其相依性。我們目前正努力為 Sandmark 新增更多的 Coq 回歸效能評測。
-
ocaml-bench/sandmark#122 程式碼大小的測量
基準測試的程式碼大小是
flambda
分支所需的一項測量,我們正在研究是否將其添加到 Sandmark 基準測試運行中。 -
ocaml-bench/sandmark#142 [RFC] 使用者應如何設定 Sandmark 執行?
我們正在收集使用者回饋和關於如何設定 Sandmark 基準測試的建議。請在此討論中分享您的想法和評論。
-
ocaml-bench/sandmark#150 可運作的 Coq 檔案
在 Sandmark 中新增更多用於效能評測的 Coq 檔案。
已完成
Dune 2.6.0 升級
-
ocaml-bench/sandmark#131 更新解壓縮效能評測
@dinosaure 更新了解壓縮效能評測,以使用 dune.2.6.0 的最新 decompress.1.1.0。
-
ocaml-bench/sandmark#132 更新相依性套件以使用 dune.2.6.0 和 Multicore OCaml 4.10.0
Sandmark 現在已更新為使用 dune.2.6.0 和 Multicore OCaml 4.10.0,並升級了 30 多個相依性套件。您可以使用以下指令測試它:
$ opam install dune.2.6.0 $ make ocaml-versions/4.10.0+multicore.bench
Coq 效能評測
-
ocaml-bench/sandmark#140 使用 Sandmark 編譯 coqc
Coq 編譯器已作為相依性套件新增至 Sandmark,現在允許我們建置和執行 Coq 效能評測。
-
ocaml-bench/sandmark#143 新增 Coq 程式庫 fraplib 和一個依賴它的基準測試
現在 Sandmark 中已包含 Formal Reasoning About Programs 書籍的
fraplib
程式庫基準測試。 -
ocaml-bench/sandmark#144 新增 frap 作為 Coq 效能評測
CompilerCorrectness.v
Coq 檔案已新增為 Sandmark 中 Coq 的測試基準。
持續整合
-
ocaml-bench/sandmark#136 在 .drone.yml 中使用 BUILD_ONLY
已更新 .drone.yml 檔案,以使用 BUILD_ONLY 環境變數來僅安裝相依性,而不執行 CI 的基準測試。
-
ocaml-bench/sandmark#147 新增對關聯基準測試標籤的支援
引入了
macro_bench
和run_in_ci
標籤來與基準測試關聯。標記為run_in_ci
的基準測試將作為 Sandmark CI 的一部分執行。
雜項
-
ocaml-bench/sandmark#124 在 Makefile 中新增使用者可設定的 paramwrapper
現在可以將
--cpu-list
指定為PARAMWRAPPER
環境變數,以執行平行基準測試。 -
ocaml-bench/sandmark#134 在 README 中包含更多資訊
已更新 README 以包含文件,以反映 Sandmark 的最新變更。
-
ocaml-bench/sandmark#141 使用其他選項豐富變體
現在
ocaml-versions/*
檔案使用 JSON 檔案格式,可讓您指定 ocaml-base-compiler 來源 URL、configure
選項和OCAMLRUNPARAMS
。以下提供範例:{ "url" : "https://github.com/ocaml-multicore/ocaml-multicore/archive/parallel_minor_gc.tar.gz", "configure" : "-q", "runparams" : "v=0x400" }
-
ocaml-bench/sandmark#146 將主幹從 4.11.0 更新至 4.12.0
Sandmark 現在使用最新的 OCaml 4.12.0 作為 ocaml-versions/ 中的主幹。
-
ocaml-bench/sandmark#148 安裝 python3-pip 和 intervaltree 以進行乾淨的 CI 建置
已更新 .drone.yml 檔案以安裝
python3-pip
和intervaltree
軟體套件,以避免呼叫 Makefile 時發生錯誤。
OCaml
進行中
-
ocaml/ocaml#9722 再次針對 EINTR 的信號
此修補程式提供新的實作來解決鎖定和信號處理問題。
-
ocaml/ocaml#9756 垃圾收集器顏色變更
此 PR 移除垃圾收集器 (GC) 顏色配置中的灰色,以便與 Multicore OCaml 主要收集器一起使用。
已完成
-
ocaml/dune#3576 在 OCaml 4.12.0 中,空的封存檔不再產生 .a 檔案
永遠不會為空的程式庫產生原生封存檔,這修正了與 OCaml 4.12.0 處理空封存檔時的相容性問題。
-
ocaml/ocaml#9541 為儀器化運行時間新增手冊頁
根據審查意見更新了
manual/manual/cmds/instrumented-runtime.etex
文件,並已合併到 stock OCaml 中。 -
ocaml/ocaml#9728 簡化了不含分頁表的壓縮
使用自我描述的閉包表示法來簡化壓縮器,並擺脫分頁表。
我們要感謝社群中所有 OCaml 開發人員和使用者,感謝他們對 multicore OCaml 專案的持續支援、程式碼審查、文件和貢獻。
縮寫
- CI:持續整合
- DEC:網域執行環境
- GC:垃圾收集器
- OPAM:OCaml 套件管理器
- PR:提取請求
- RFC:請求評論
- RPC:遠端程序呼叫