OCaml 多核 - 2021年10月
欢迎阅读 2021 年 10 月的 多核 OCaml 月度报告!此更新以及 之前的更新 由我、@ctk21、@kayceesrk 和 @shakthimaan 共同整理。
正如 @octachron 上个月宣布的那样,核心团队已 承诺明年发布 OCaml 5.0,其中包含多核和效果运行时。本月,我们的多核代码库中出现了大量的活动,以准备一个对上游友好的版本,并进行了一些更改,使代码准备好用于 ocaml/ocaml
并减少差异的大小。回想一下,自从 OCaml 4.09 开始,我们就一直在稳步地引入与多核相关的更改,因此我们现在只剩下一些非常大的部分。因此,主线 OCaml 主干代码现在正在持续合并到我们的 5.00 暂存分支中,并且测试覆盖率也相应地提高了。
在标准库中,我们继续致力于默认情况下提高线程安全性。由于效果处理程序也已确认将进入 5.0,因此它们现在在 stdlib 中也有了自己的模块。多核库生态系统也随着支持 OCaml 5.00 的更改而发展,特别是,随着更多用例的积累,Domainslib 进行了重大更新和改进。Sandmark 性能测试工具与 current-bench 的集成也正在积极进行中。
我们要感谢以下人员的贡献
- Török Edwin 能够重现
Task.pool
管理中的错误 Domainslib#43,并且还提供了一个 PR 来修复它。 - Sid Kshatriya 为
Eio
创建了 PR#83 以使用效果处理程序模块。
我们 11 月份的重点将继续放在不懈地构建 5.0 暂存树上,并且我们正在准备与 OCaml 核心团队进行一系列工作组(持续整整一周)以对完整的补丁集进行初步代码审查。请关注 12 月初的结果!
与往常一样,首先列出的是多核 OCaml 更新,其中包含上游工作、与主干的合并、测试用例的更新、错误修复和文档改进。接下来是 Domainslib、Tezos
和 Eio
的生态系统更新。最后列出 Sandmark 和 current-bench 任务以供参考。
多核 OCaml
正在进行
上游
-
ocaml-multicore/ocaml-multicore#637
caml_page_table_lookup
在 ocaml-multicore 中不可用删除页面表功能的残余部分 PR 现在应该可以解决此问题。
-
ocaml-multicore/ocaml-multicore#707 将
Domain.DLS
移动到 ThreadLocal 模块并在 systhreads 下使其工作Domain.DLS
实现将移动到ThreadLocal
模块,并且还应该启用对线程本地存储到 systhreads 的使用。 -
ocaml-multicore/ocaml-multicore#719 优化
minor_gc
的 ephemeron 处理一个优化请求,要求单个域使用主干算法在次要 GC 中收集 ephemerons,并且在多域上下文中没有 ephemerons 时不使用屏障。
-
ocaml-multicore/ocaml-multicore#727 更新版本号
ocaml-variants.opam
文件需要更新为使用ocaml-variants.4.14.0+domains
。 -
ocaml-multicore/ocaml-multicore#728 更新 5.00 分支的
base-domains
包base-domains
包需要包含4.14.0+domains
,因为在本地 opam 切换上固定会失败依赖项解析。
测试套件
-
ocaml-multicore/ocaml-multicore#656
Core
测试套件工作流程一个实现工作流程的草稿 PR,每天运行一次 Core 的测试套件。
-
ocaml-multicore/ocaml-multicore#720 提高 ephemerons 与测试套件的兼容性
该 PR 导入上游修复程序以使 ephemerons 与中缀对象一起使用,并为
weaktest.ml
提供修复程序。 -
ocaml-multicore/ocaml-multicore#722 测试套件:重新启用
signals_alloc
测试用例signals_alloc
测试用例已启用,并且该 PR 还尝试确保字节码解释器轮询信号。 -
ocaml-multicore/ocaml-multicore#723 GitHub Action MacOS 运行程序上的
beat.ml
失败对 CI 执行运行的测试套件中
beat.ml
测试失败进行调查。
其他
-
ocaml-multicore/ocaml-multicore#669 为域设置线程名称
一个为多核 OCaml 实现线程命名的补丁。它提供了一个接口,可以以不同的方式命名域和线程。
-
ocaml-multicore/ocaml-multicore#698 将空闲池返回给操作系统
pool_release
位于 shared_heap 中,不会将内存返回给操作系统。关于保留多少内存以及使用空间开销设置回收多少内存的持续讨论。 -
ocaml-multicore/ocaml-multicore#703 当没有域可以处理阻塞信号时,
caml_enter_blocking_section
中可能存在循环当存在阻塞特定信号集的域且没有其他域可以处理该信号时,可能会触发这种情况,并且可能是由
caml_enter_blocking_section
中的循环引起的。 -
ocaml-multicore/ocaml-multicore#725 阻塞信号无限循环修复
已引入单调
recorded_signals_counter
以修复当没有域可以处理阻塞信号时caml_enter_blocking_section
中可能存在的循环。 -
ocaml-multicore/ocaml-multicore#726 并发修改对象的编组是不安全的
必须正确处理在不同域上被修改的对象的编组,并且应该是安全的。它不应导致分段错误或崩溃。
已完成
上游
构建
-
ocaml-multicore/ocaml-multicore#662 在 5.0 上禁用更改检查
.github/workflows/hygiene.yml
已更新为在 5.00 上禁用检查,以避免更改条目中的噪音。 -
ocaml-multicore/ocaml-multicore#676 修复 5.00 安装
caml/byte_domain_state.tbl
已删除,并且README.adoc
已重命名为README.stock.adoc
,以便使用 OCaml 5.00 分支干净地构建。
更改
-
ocaml-multicore/ocaml-multicore#675 将
Bytes.unsafe_of_string / Bytes.unsafe_to_string
与 OCaml 主干对齐bytecomp/bytegen.ml
中使用的Pbytes_to_string / Pbytes_of_string
现在与上游 OCaml 对齐。 -
ocaml-multicore/ocaml-multicore#677 删除调试 nop
调试 nop 原语对于上游来说不是必需的,并且已被清理。该 PR 还修复了
emit.mlp
中 check-typo 的空格,使其与主干匹配。 -
ocaml-multicore/ocaml-multicore#679 删除
caml_read_field
caml_read_field
的使用已被删除,因为现有的Field
提供了所有必要的信息,使其更接近上游 OCaml。 -
ocaml-multicore/ocaml-multicore#681 回退到 otherlibs/unix 的 ocaml/trunk 版本
unixsupport.c
、cstringv.c
和otherlibs/unix
中的文件已更新,使其类似于ocaml/ocaml
。 -
ocaml-multicore/ocaml-multicore#684 删除
lambda/matching
中的历史for_handler
和Reperform_noloc
lambda/matching.ml{,i}
中的for_handler
函数和Reperform_noloc
不需要上游,因此已被删除。 -
ocaml-multicore/ocaml-multicore#685 从 interp.c 中删除
Init_field
interp.c
文件已更新,使其更接近ocaml/ocaml
。已修复 check-typo 错误,并且Init_field
宏已被清理。 -
ocaml-multicore/ocaml-multicore#704 从 Domain 中删除 Sync.poll 和纳秒
Domain 模块已更新,仅包含上游所需的变化。
Domain.Sync.poll
和Domain.nanosecond
已删除。Domain.Sync.cpu_relax
已重命名为Domain.cpu_relax
。platform.h
已更新,其中包含 check-typo 的修复程序。 -
ocaml-multicore/ocaml-multicore#706 将
otherlibs/win32unix
回退到 ocaml/trunkotherlibs/win32unix/*
文件已更新,使其更接近ocaml/ocaml
。 -
ocaml-multicore/ocaml-multicore#708 删除 maybe stats
输出统计信息的
caml_maybe_print_stats
原语和OCAMLRUNPARAM
的s
选项现已删除。 -
ocaml-multicore/ocaml-multicore#724 运行时:从
io.h
中删除未使用的字段从
runtime/caml/io.h
中删除revealed
和old_revealed
,因为它们也已从ocaml/ocaml
中删除。
差异
-
ocaml-multicore/ocaml-multicore#663 从
typing/
上游的差异中删除噪音该 PR 压缩了
typing/
上游 OCaml 的不必要的差异。 -
ocaml-multicore/ocaml-multicore#664 删除
parsing/
中与上游的不必要的差异该 PR 删除了
parsing/
中与上游 OCaml 的不必要的空格差异。 -
ocaml-multicore/ocaml-multicore#694 改善启动代码差异的第一步
此 PR 试图改进 trunk 和 Multicore OCaml 启动代码中的差异。
-
ocaml-multicore/ocaml-multicore#695 提升 systhread 与 trunk 的差异
通过合并此 PR,systhread 与 trunk 的差异得到了改进。
合并
-
ocaml-multicore/ocaml#2 将 trunk 更新到最新的上游 trunk
此 PR 旨在帮助解决 OCaml 5.0 的差异输出问题。通过这些更改,您可以成功执行
make && make tests
。结果摘要如下所示Summary: 2918 tests passed 40 tests skipped 0 tests failed 105 tests not started (parent test skipped or failed) 0 unexpected errors 3063 tests considered
-
ocaml-multicore/ocaml#3 最新的 5.00 提交
trunk 的最新提交现已合并到 ocaml-multicore 5.00 分支。
-
ocaml-multicore/ocaml-multicore#718 弃用 Domain 中的 Sync 和
timer_ticks
此补丁将
4.12.0+domains+effects
的更改与主线 5.00 分支同步。
线程安全
-
ocaml-multicore/ocaml-multicore#632
Str
模块的多域安全性PR#635 使
lib-str
域安全,以便与 Multicore OCaml 并发工作。 -
ocaml-multicore/ocaml-multicore#672 Codefrag 线程安全性
此 PR 引入了一个无锁跳表,使 codefrag 线程安全。代码片段不能在移除后立即释放,但会被添加到一个列表中,并在稍后的停止世界暂停期间清理。
修复
-
ocaml-multicore/ocaml-multicore#655 Systhreads:将
thread_next_id
初始化为 0thread_next_id
未初始化,导致 Core 的测试套件出现问题。现在已将其初始化为零。 -
ocaml-multicore/ocaml-multicore#657 Libstr:使用域局部值存储
last_search_result_key
last_search_result_key
现在存储在域本地存储中,这修复了最近的 CI 故障。 -
ocaml-multicore/ocaml-multicore#673 修复 #671 中报告的 C++ 命名空间污染
此补丁修复了 C++ 命名空间污染和拼写检查问题。
-
ocaml-multicore/ocaml-multicore#702 Otherlibs:将 PR10478 修复程序添加回 systhreads
st_thread_set_id
调用已添加到otherlibs/systhreads/st_stubs.c
中,这重新启用了来自 ocaml/ocaml#10478 的 systhreads 修复程序。 -
ocaml-multicore/ocaml-multicore#721 修复
make install
运行
make install
时出现的caml/byte_domain_state.tbl: No such file or directory
错误已通过此 PR 修复。
测试套件
-
ocaml-multicore/ocaml-multicore#654 启用效果测试
由于语法支持已添加到 Multicore OCaml 中,因此效果处理程序测试现已重新添加。
-
ocaml-multicore/ocaml-multicore#658 启用最后一个 dynlink 测试
lib-dynlink-private
测试现已在 CI 中启用运行。 -
ocaml-multicore/ocaml-multicore#659 重新导入 threadsigmask 测试并删除 systhread-todo 测试目录
systhreads 中缺少的关于信号处理和滴答线程的
lib-systhreads-todo
测试已在 CI 中重新激活。 -
ocaml-multicore/ocaml-multicore#660
testsuite/disabled
文件的修复和整理已修复 80 字符行限制的
check-typo
问题以及testsuite/disabled
中不必要的test/promotion
。 -
ocaml-multicore/ocaml-multicore#661 测试套件:重新启用 pr9971
pr9971
测试已重新启用,以便在 CI 中运行。 -
ocaml-multicore/ocaml-multicore#688 改善 systhreads 中的信号处理
对 systhreads 中的信号处理进行了改进,修复了 CI 中
threadsigmask
测试用例的失败。 -
ocaml-multicore/ocaml-multicore#712 Otherlibs:Unix.kill 应该检查挂起的信号
已重新启用
unix_kill
测试用例,以确保Unix.kill
在返回时检查挂起的信号。
文档
-
ocaml-multicore/ocaml-multicore#672 修复
major_gc
的拼写检查错误,以避免 #672 中的更改被覆盖一个修复
runtime/major_gc.c
中拼写检查错误的补丁。 -
ocaml-multicore/ocaml-multicore#696 Stdlib:修复
effectHandlers.mli
中的拼写错误已修复
stdlib/effectHandlers.mli
中的一些拼写错误。 -
ocaml-multicore/ocaml-multicore#697 删除死代码并清理次要 GC 中的注释
一个非功能性更改,用于清理次要和主要 GC 文件中的注释。
-
ocaml-multicore/ocaml-multicore#699 清理 fiber 实现并添加文档
已删除
amd64.S
中未使用的代码并修复了格式。不再需要在堆栈顶部添加 24 字节以进行外部调用,并且已将其删除。 -
ocaml-multicore/ocaml-multicore#713 阐明 Lazy 关于 RacyLazy 和 Undefined 异常的文档。
已更新
stdlib/lazy.mli
中的文档,以阐明try_force
的行为和线程安全性。 -
ocaml-multicore/ocaml-multicore#717 严格化
minor_gc.c
中的代码注释此 PR 解释了如何提升 ephemeron 密钥以避免引入屏障,并使用
/* ... */
样式的注释。 -
OCaml 5.00 的文档存储库,其中包含设计和建议的上游计划。
效果处理程序
-
ocaml-multicore/ocaml-multicore#653 删除
drop_continuation
此 PR 已被 添加 EffectHandlers 模块的 PR 取代,用于 4.12.0+domains+effects。
-
ocaml-multicore/ocaml-multicore#682 将效果处理程序移动到 Stdlib 中的独立模块
Obj
中的EffectHandlers
功能现已移动到 Stdlib 中的独立模块。 -
ocaml-multicore/ocaml-multicore#687 将效果处理程序移动到 Stdlib 中的独立模块
这是 PR#682 的回传,用于
4.12+domains
。 -
ocaml-multicore/ocaml-multicore#689 添加 EffectHandlers 模块
此 PR 将效果处理程序函数添加到
4.12.0+domains+effects
中,并允许带有效果处理程序函数的domainslib
与4.12.0+domains+effects
开关一起工作。
杂项
-
ocaml-multicore/ocaml-multicore#678 使字节码和原生模式下的域状态相同
struct domain_state
结构现在在字节码和原生代码中都相同。 -
ocaml-multicore/ocaml-multicore#691 添加中断时带有回溯的功能
回溯对于建模异步/等待很有用,尤其是在等待的任务引发异常时,回溯包含等待和正在等待的任务的框架。
-
ocaml-multicore/ocaml-multicore#693 添加中断时带有回溯的功能
ocaml-multicore/ocaml-multicore#691 到
4.12.0+domains+effects
的回传。 -
ocaml-multicore/ocaml-multicore#701 当并行使用预定义格式化程序时真正刷新输出
刷新以前仅在域终止时发生,但通过此 PR,输出会立即刷新。
-
ocaml-multicore/ocaml-multicore#705 Otherlibs:从 systhreads 中删除
caml_channel_mutex_io
钩子systhreads 中的
caml_channel_mutex_io
钩子现已删除。 -
ocaml-multicore/ocaml-multicore#716 runtime:
extern_free_position_table
应该在extern_flags & NO_SHARING
时返回extern_free_position_table
应该在extern_flags & NO_SHARING
时立即返回,与extern_alloc_position_table
对称。
生态系统
正在进行
Domainslib
-
ocaml-multicore/domainslib#43
Task.pool
管理中可能存在错误Török Edwin 使用 4.12.0+domains 和 AMD Ryzen 3900X CPU 上的 domainslib 0.3.1 重现了分段错误,并且还提供了一个带有修复程序的草稿 PR!
-
ocaml-multicore/domainslib#46 提供一种遍历所有池的方法
需要能够遍历 domainslib 中创建的所有池。一个用例是拆除所有池。可以使用弱哈希集来存储指向池的弱指针。
-
ocaml-multicore/domainslib#47
Task.await
死锁(任务已完成但 await 永远不会返回)关于在
Task.async
内部嵌套Task.await
以及在Task.async
内部嵌套Task.async
的查询。还提供了一个代码片段、堆栈跟踪和平台信息来重现死锁场景。 -
ocaml-multicore/domainslib#48 将
ws_deque
移动到 lockfree请求将 domainslib 中的工作窃取双端队列移动到
ocaml-multicore/lockfree
,并使domainslib
依赖于此新的lockfree
实现。 -
ocaml-multicore/domainslib#49 我们是否应该从库中公开多通道?
关于 Multicore OCaml 用户是否会发现非 FIFO 多通道实现有用的查询。Domainslib 已经提供了 FIFO 通道。
-
ocaml-multicore/domainslib#50 Multi_channel:允许每个程序使用不同配置创建多个实例
Török Edwin 在
lib/multi_channel.ml
和lib/task.ml
中贡献了一个草稿 PR,用于删除使用全局密钥并改用每个通道密钥。 -
ocaml-multicore/domainslib#51 利用效果处理程序
任务现在使用效果处理程序创建,并且新的
test_deadlock.ml
测试了相同的功能。此更改仅适用于4.12+domains
和5.00
。来自图灵机(Intel Xeon Gold 5120 CPU @ 2.20 GHz,28 个隔离核心)的性能结果如下所示
杂项
-
ocaml-multicore/tezos#8 ci.Dockerfile 抛出警告
Ubuntu 20.10 上的
ci.Dockerfile
在使用 GCC 10.3.0 时会对_Atomic
抛出 C99 警告。 -
ocaml-multicore/tezos#10 修复 make build-deps,修复 NixOS 支持
conf-perl
在上游不再需要,并且已从tezos-opam-repository
中删除。此补丁还修复了make build-deps/build-dev-deps
。 -
ocaml-multicore/ocaml-uring#39 NixOS 上的测试失败
ocaml-uring
主分支在 NixOS 上使用dune runtest
显示测试失败。 -
ocaml-multicore/eio#85 有计划支持
js_of_ocaml
吗?Konstantin A. Olkhovskiy(
Lupus
)询问 EIO 是否可以编译到 JavaScript 后端,假设js_of_ocaml
支持 effects。
已完成
Domainslib
-
ocaml-multicore/domainslib#45 添加命名池
现在在设置期间添加了一个可选参数来命名池。此名称可用于稍后检索池。
-
ocaml-multicore/domainslib#52 使用随机数作为缓存前缀以在 CI 中禁用缓存
现在在
.github/workflows/main.yml
中,cache-prefix
使用随机数来在 CI 中禁用缓存。 -
ocaml-multicore/domainslib#53 在 PR#704 之后使 domainslib 能够使用 OCaml 5.00 构建/运行
CI 已更新,现在可以使用 OCaml 5.00 分支进行构建和运行。
-
ocaml-multicore/domainslib#54 使用最新的 4.12+domains+effects 哈希值作为缓存键
缓存键现在使用来自 OCaml Multicore 的最后一个提交哈希值,以便在 CI 中使缓存失效。
其他
-
ocaml-multicore/tezos-opam-repository#3 添加 domainslib
domainslib.0.3.1
版本现在已作为软件包包含在 Tezos OPAM 存储库中。 -
ocaml-multicore/retro-httpaf-bench#17 改善图表
现在已在从 Jupyter notebook 生成的图表中添加了标记,以便轻松区分颜色线条。
-
ocaml-multicore/multicore-opam#59 在 ocaml-multicore/ocaml-multicore#514 之后修复 batteries
batteries-included
的batteries.3.3.0+multicore
opam 文件已使用正确的 src URL 进行更新。 -
ocaml-multicore/eio#82 迁移到 4.12.0+domains effects 实现(无语法 effects 版本)
此 PR 更新了
eio
以支持 OCaml 5.0 版本的 effects 实现。 -
ocaml-multicore/eio#83 Effect 处理程序现在有自己的模块
Sid Kshatriya 贡献了一个补丁,将
Obj.Effect_handlers
重命名为EffectHandlers
,因为 effect 处理程序在 Stdlib 中有自己的模块。 -
Jane Street 的标准库覆盖层
core
现在已添加到ocaml-multicore
GitHub 项目存储库中。
基准测试
Sandmark
正在进行
-
ocaml-bench/sandmark#248 Coq 构建失败
一个新的 Coq tarball,coq-multicore-2021-09-24,可以使用 Multicore OCaml 4.12.0+domains 构建,但是,
stdio.v0.14.0
无法使用 4.14.0+trunk 顺利构建,因为存在已报告的dune 问题。 -
ocaml-bench/sandmark#260 添加用于顺序运行的 5.00 分支。修复笔记本。
一个新的 5.00 OCaml 变体分支已添加到 Sandmark,以跟踪 CI 中的顺序基准运行。
已完成
-
ocaml-bench/sandmark#256 删除旧变体
旧变体
4.05.*
、4.06.*
、4.07.*
、4.08.*
、4.10.0.*
现已从 Sandmark 中删除。 -
ocaml-bench/sandmark#258
在 README 中记录 Makefile 变量README 现在包含有关在 Sandmark 中构建和执行基准测试期间使用的各种 Makefile 变量的文档。
current-bench
正在进行
-
ocurrent/current-bench#117 从 Docker 容器读取 stderr
出于调试目的,我们希望查看 Docker 容器内基准执行的任何构建失败。
-
ocurrent/current-bench#146 复制 ocaml-bench-server 设置
需要将 TAG 和 OCaml 变体从 Sandmark Makefile 抽象到 current-bench,以便能够为不同的编译器版本和开发者分支运行基准测试。
已完成
-
ocurrent/current-bench#105 将 Docker 镜像名称从
pipeline/lib/pipeline.ml
抽象到环境中现在支持自定义 Dockerfile,因此您可以在 Dockerfile 中提取任何 opam 镜像。
-
ocurrent/current-bench#119
OCAML_BENCH_DOCKER_CPU
不支持用于并行执行的 CPU 范围Docker CPU 设置现在使用字符串表示而不是整数来指定用于并行执行的 CPU 列表。
-
ocurrent/current-bench#151 Docker 与本地性能
使用 current-bench 的 Docker 以及本地顺序和并行基准运行在禁用超线程的情况下没有显示出明显的差异。下面提供了 Gödel 服务器配置和 Sandmark-nightly notebook 图表结果以供参考
- CPU:Intel(R) Xeon® Gold 5120 CPU @ 2.20 GHz
- OS:Ubuntu 20.04.3 LTS (Focal Fossa)
- Sandmark 2.0-beta 分支:https://github.com/ocaml-bench/sandmark/tree/2.0-beta
- 已禁用超线程
$ cat /sys/devices/system/cpu/smt/active 0
- 内存 (62 GB),磁盘 (1.8 TB)。
- OCaml 变体:4.12.0+domains
- Sandmark-nightly 笔记本:https://github.com/ocaml-bench/sandmark-nightly/tree/main/notebooks
- 每个基准测试五次迭代的平均值
run_in_ci
用于顺序macro_bench
用于并行
时间 标准化 堆顶词 标准化
MaxRSS (KB) 标准化
主要收集 标准化
并行基准测试
(请参阅 PR 全文以获取完整的图表集,包括主要词语和花费的时间)
我们特别感谢社区中所有 OCaml 用户、开发人员和贡献者,感谢他们宝贵的时间和对项目的持续支持。请注意安全!
缩略语
- AMD:超微半导体公司
- CI:持续集成
- CPU:中央处理器
- DLS:域本地存储
- FIFO:先进先出
- GB:千兆字节
- GC:垃圾回收器
- GCC:GNU 编译器集合
- IO:输入/输出
- OPAM:OCaml 包管理器
- OS:操作系统
- PR:拉取请求
- TB:太字节
- URL:统一资源定位符