OCaml 多核 - 2021 年 4 月
多核 OCaml:2021 年 4 月
欢迎来到 2021 年 4 月的 多核 OCaml 月度报告!我在印度的朋友和同事正在经历可怕的第二波新冠疫情,但他们仍在努力为多核 OCaml 项目提供所有更新。本月的更新以及 以前的更新 由我、@kayceesrk 和 @shakthimaan 共同整理。
上游 OCaml 4.13 开发
GC 安全点仍然是多核 OCaml 4.13 版本开发的重点。虽然可能看起来很安静,只有一个 PR 正在进行中,但你也可以看看 编译器分支,在那里一群勇敢的编译器后端黑客一直在改进设计。你也可以在第一份 核心编译器开发通讯 中找到更多关于正在进行的上游工作的详细信息。引用 @xavierleroy 的话:“这是一个非凡的改变,涉及到一个新的静态分析和每个代码发射器的一些调整,但现在一切看起来都很不错。”
多核 OCaml 树
切换到使用 OCaml 4.12 现在已经完成,所有开发 PR 现在都针对该版本工作。我们已经投入了大量精力来确定是否应该将域本地分配缓冲区 (ocaml-multicore#508) 纳入最初的 5.0 修补程序中。
什么是 DLAB?在较大的核心数量(高达 128 个)上测试多核时,我们观察到,从次要 GC(每个域一个)中,有很多值的提前提升。引入 DLAB 的目的是鼓励域拥有更多保持堆本地值的,这应该提高了可扩展性。但是,计算机就是计算机,我们发现结果恰恰相反——虽然在 DLAB 活动的情况下,提前提升的数量有所减少,但总体性能要么持平,要么甚至更低!我们仍在努力分析以找出根本原因——现代架构具有复杂的非一致性和分层内存和缓存拓扑结构,它们以意想不到的方式相互影响。请关注下个月关于此决定的月度报告,或者直接关注 ocaml-multicore#508!
多核生态系统
除此之外,多核 OCaml 项目的测试套件覆盖率得到了显著改善,我们正在继续为该项目添加越来越多的测试。请继续贡献并行基准测试。关于基准测试,我们已经能够使用 current-bench 持续基准测试框架构建 Sandmark-2.0 基准测试,该框架提供 GitHub 前端和 PostgreSQL 数据库来存储结果。Dune 等其他一些项目也开始使用 current-bench,这很好——一旦它更加成熟,将其建立在核心 OCaml 项目上将是件好事。
我们还推出了一个 特定于多核的 CI,它可以对 opam 包进行差异测试(例如,帮助隔离某个问题是特定于多核的故障,还是上游 OCaml 上的通用编译错误)。我们现在 正在将其推向生产,这意味着我们可以开始接受可能从多核中受益的项目。**如果你在 opam 上有一个项目可以从使用多核 OCaml 中获益,并且它可以在 4.12 上编译,那么请与我们联系**。我们最初会合并我们熟悉的代码库,但我们需要更多样的来源来获得良好的覆盖率。我们唯一需要的是项目内可以与我们一起进行集成的响应式联系人。如果我们对这个呼吁得到良好的响应,我们将开始报告项目状态。
和往常一样,我们首先从多核 OCaml 的正在进行和已完成的任务开始。接下来是 Sandmark 基准测试项目更新,以及 current-bench 项目中相关的多核 OCaml 特性请求。最后,提及上游 OCaml 工作供您参考。
多核 OCaml
正在进行
测试
-
ocaml-multicore/domainslib#23 运行测试:从
run_test
目标中的手动命令迁移到dune runtest
目前,测试使用 Makefile 中的显式 exec 命令执行,目标是迁移到使用
dune runtest
命令。 -
ocaml-multicore/ocaml-multicore#522 使用 -O0 而不是 -O2 构建运行时会导致测试套件失败
使用
-O0
优化会导致运行时测试失败,而-O2
优化会成功。需要进一步调查。 -
ocaml-multicore/ocaml-multicore#526 weak-ephe-final issue468 在非常小的次要堆上可能会失败
目前正在调查
weak-ephe-final
测试中使用小型次要堆(4096 字)时 issue468 测试失败的原因。 -
ocaml-multicore/ocaml-multicore#528 扩展 CI 运行
PR 实施了并行的 "callback" "gc-roots" "effects" "lib-threads" "lib-systhreads" 测试,使用
taskset -c 0
选项,并使用小型次要堆。需要增强 CI 覆盖率,添加更多变体和优化标志。 -
ocaml-multicore/ocaml-multicore#542 添加 ephemeron 延迟测试
添加测试以涵盖 ephemerons、延迟值和域生命周期以及 GC。
-
ocaml-multicore/ocaml-multicore#545 ephetest6 在域数量较多时会失败
测试
ephetest6.ml
在创建更多域时会失败,有时还会死锁。 -
ocaml-multicore/ocaml-multicore#547 调查 weaktest.ml 失败
weaktest.ml
在测试套件中被禁用,因为它失败了。需要进一步调查。 -
ocaml-multicore/ocaml-multicore#549 zmq-lwt 测试失败
opam-ci 错误报告了
zmq-lwt
测试失败。它抛出了 Zmq.ZMQ_exception,并带有Context was terminated
错误消息。
杂项
-
ocaml-multicore/ocaml-multicore#508 域本地分配缓冲区
域本地分配缓冲区实现的代码审查及其相应更改正在积极进行中。
-
ocaml-multicore/ocaml-multicore#514 更新 ocaml-variants.opam 中的说明
ocaml-variants.opam
和configure.ac
已更新,现在使用多核 OCaml 存储库。我们希望+domains
和+domains+effects
分支具有不同的版本字符串。 -
ocaml-multicore/ocaml-multicore#527 将 eventlog 移植到 CTF
关于将
eventlog
实现移植到通用跟踪格式的代码审查正在进行中。已经进行了相关的代码更改,并且测试通过了。 -
ocaml-multicore/ocaml-multicore#529 纤维大小控制和统计
一个特性请求,用于设置纤维的最大堆栈大小,以及获取相同的内存统计信息。
已完成
上游
-
ocaml-multicore/ocaml-multicore#533 Systhreads 同步使用 pthread 函数
现在直接使用
pthread_*
函数,而不是caml_plat_*
函数,以与 OCaml 主干保持一致。现在会引发Sys_error
,而不是Fatal error
。 -
ocaml-multicore/ocaml-multicore#535 删除多核统计信息收集
现在从多核 OCaml 中删除了可配置的统计信息收集功能。这大大减少了与主干的差异,并简化了上游合并。
-
ocaml-multicore/ocaml-multicore#536 删除 emit_block_header_for_closure
emit_block_header_for_closure
现在不再使用,因此已从 asmcomp 源代码中删除。 -
ocaml-multicore/ocaml-multicore#537 移植 @stedolan 的 "在 amd64 上微优化分配以节省寄存器"
在 amd64 上微优化分配以节省寄存器的上游更改现在已移植到多核 OCaml。这大大减少了 amd64 的 emit.mlp 上的差异。
增强功能
-
ocaml-multicore/ocaml-multicore#531 使本机堆栈大小限制可配置(并修复 Gc.set)
现在可以通过
Gc.set
接口配置本机纤维的堆栈大小限制。 -
ocaml-multicore/ocaml-multicore#534 将分配大小信息移动到帧描述符
现在使用帧描述符传播分配大小信息,以便 statmemprof 可以跟踪它们。
-
ocaml-multicore/ocaml-multicore#548 Mutex、Condition 和 Semaphore 的多核实现
Mutex
、Condition
和Semaphore
模块现在与 stdlib 功能完全兼容,可以与Domain
一起使用。
测试
-
ocaml-multicore/ocaml-multicore#532 添加了对带有主循环的终结器回调的测试
更新了
test_finaliser_gc.ml
代码,其中添加了一个测试,该测试在注册表中有一个根的情况下运行终结器。 -
ocaml-multicore/ocaml-multicore#541 添加了一个并行 tak 测试用例
现在已将并行测试用例添加到存储库中,以对次要堆施加压力,并在不调用
Gc
函数或域终止的情况下有机地进入次要 GC。 -
ocaml-multicore/ocaml-multicore#543 并行版本的 weaklifetime 测试
现在已将
weaklifetime.ml
测试的并行实现添加到测试套件中,其中多个域访问 Weak 结构。 -
ocaml-multicore/ocaml-multicore#546 域_dls 和 ephetest_par 测试中对域生命周期的覆盖
对
domain_dls.ml
和ephetest_par.ml
的改进,以更好地覆盖域生命周期测试。
修复
-
ocaml-multicore/ocaml-multicore#530 修复 gc_regs 存储桶的 off-by-1 问题
现在修复了在堆栈中扫描以查找上一个
gc_regs
存储桶的位置时的 off-by-1 错误。 -
ocaml-multicore/ocaml-multicore#540 修复小型分配重试
Alloc_small
宏没有处理 GC 函数没有返回具有足够大小的次要堆的情况,此 PR 修复了该问题以及代码清理。
生态系统
-
ocaml-multicore/retro-httpaf-bench#3 将 cohttp-lwt-unix 添加到基准测试
现在已将
cohttp-lwt-unix
基准测试添加到retro-httpaf-bench
包中,以及对 Dockerfile 的更新。 -
ocaml-multicore/domainslib#22 将 CI 移动到 4.12 多核和 Github Actions
CI 已切换为使用 GitHub Actions 而不是 Travis。CI 中使用的 Multicore OCaml 版本现在是 4.12+domains+effects。
-
ocaml-multicore/mulicore-opam#51 更新 merlin 和 ocaml-lsp 的安装说明以适用于 4.12 变体
README.md 已更新,其中包含使用 merlin 和 ocaml-lisp 的说明,适用于
4.12+domains
和4.12+domains+effects
分支。 -
dwarf_validator DWARF 验证工具
eh_frame_check.py
中的 DWARF 验证工具现在在公共存储库中可用。它在执行时单步执行二进制文件,并使用 DWARF 指令展开堆栈。
杂项
-
ocaml-multicore/ocaml-multicore#523 Systhreads Mutex 抛出 Sys_error
Systhreads Mutex 错误检查现在与 OCaml 保持一致,如 在线程库中使用“错误检查”互斥体 中所述。
-
ocaml-multicore/ocaml-multicore#525 添加禁用信号处理测试的 issue URL
使用 issue URL ocaml-multicore#517 更新了
testsuite/disabled
,以便将来进行跟踪。 -
ocaml-multicore/ocaml-multicore#539 强制标签对 Gc.finalise 的无效参数
在强制计算时添加
Forcing_tag
以标记延迟值。这是为了在将带有Forcing_tag
的块作为参数传递时,Gc.finalise
可以引发无效参数异常。
基准测试
正在进行
沙盒
- 我们现在拥有前端,它使用 current-bench 为 CI 显示 Sandmark 2.0 版本的图形结果。下面显示了图形的原始输出。
Sandmark 2.0 基准测试正在迁移到使用 current-bench
工具。您现在可以使用 multicore
标签在 current-bench
项目中为 Multicore OCaml 项目创建必要的 issue 和 PR。
-
ocaml-bench/sandmark#209 使用规则目标 kronecker.txt 并从 macro_bench 中删除
目前正在根据代码审查建议对 graph500seq
kernel1.ml
实现进行重写。 -
ocaml-bench/sandmark#215 从 treiber_stack.ml 中删除 Gc.promote_to
我们正在更新 Sandmark 以使用 4.12+domains 和 4.12+domains+effects,此补丁从运行时中删除了 Gc.promote_to。
current-bench
-
ocurrent/current-bench#87 运行旧提交的基准测试
我们希望能够重新运行项目中较旧提交的基准测试,以便进行分析和比较。
-
ocurrent/current-bench#103 能够在 UI 上设置比例以从 0 开始
图形中绘制的原始结果需要从
[0, y_max+delta]
开始,以便更好地比较 y 轴。有一个 PR 可用于此目的,修复后的输出显示在以下图形中
-
ocurrent/current-bench#105 从
pipeline/lib/pipeline.ml
中抽象出 Docker 镜像名称Multicore OCaml 使用
ocaml/opam:ubuntu-20.10-ocaml-4.10
镜像,而pipeline/lib/pipeline.ml
使用ocaml/opam
,使用环境变量来执行此操作将非常有用。 -
ocurrent/current-bench#106 对 Multicore OCaml 使用
--privileged
选项与 Docker run_argsSandmark 环境使用
bwrap
来构建 Multicore OCaml 基准测试,因此我们需要使用--privileged
选项运行 Docker 容器。否则,构建将退出并出现Operation not permitted
错误。 -
ocurrent/current-bench#107 能够仅启动和运行 PostgreSQL 和前端
对于 Multicore OCaml,我们使用不同的配置设置配置硬件以进行各种实验,使用 ETL 工具仅将结果加载到 PostgreSQL 数据库并将其可视化在前端将非常有用。
-
ocurrent/current-bench#108 支持裸机本地构建
为了避免 Docker 的任何开销,我们需要一种方法在裸机上运行 Multicore OCaml 基准测试。
已完成
文档
-
ocurrent/current-bench#75 修复生产部署;添加说明
HACKING.md 现在已更新,其中包含有关执行 current-bench 生产部署的文档。
-
ocurrent/current-bench#90 添加一些用户可能遇到的错误的解决方案
基于我们对 current-bench 与 Sandmark-2.0 的测试,我们现在更新了 HACKING.md 文件中的常见问题解答。
杂项
-
ocurrent/current-bench#96 删除前端的硬编码 URL
现在从代码中抽象出前端 URL,以便我们可以在任何新的原始服务器上部署 current-bench 实例。
-
ocaml-bench/sandmark#204 将 layers.ml 添加为 Sandmark 的基准测试
Irmin layers.ml 基准测试现在已添加到 Sandmark 中,以及它的依赖项。它被标记为
gt_100s
。
OCaml
正在进行
-
此 PR 正在进行中。感谢 Mark Shinwell、Damien Doligez 和 Xavier Leroy 的宝贵反馈和代码建议。
特别感谢社区中的所有 OCaml 用户和开发者对项目的持续支持和贡献。保持安全!
首字母缩略词
- AMD:超微半导体
- CI:持续集成
- CTF:通用跟踪格式
- DLAB:域本地分配缓冲区
- DWARF:使用属性记录格式进行调试
- ETL:提取转换加载
- GC:垃圾收集器
- OPAM:OCaml 包管理器
- PR:拉取请求
- UI:用户界面
- URL:统一资源定位器
- ZMQ:ZeroMQ