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.opamconfigure.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 的多核实现

    MutexConditionSemaphore 模块现在与 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.mlephetest_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+domains4.12+domains+effects 分支。

  • dwarf_validator DWARF 验证工具

    eh_frame_check.py 中的 DWARF 验证工具现在在公共存储库中可用。它在执行时单步执行二进制文件,并使用 DWARF 指令展开堆栈。

杂项

基准测试

正在进行

沙盒

  • 我们现在拥有前端,它使用 current-bench 为 CI 显示 Sandmark 2.0 版本的图形结果。下面显示了图形的原始输出。

current-bench Sandmark-2.0 frontend |312x499

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 可用于此目的,修复后的输出显示在以下图形中

current-bench frontend fix 0 baseline

  • ocurrent/current-bench#105pipeline/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_args

    Sandmark 环境使用 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

正在进行

  • ocaml/ocaml#10039 安全点

    此 PR 正在进行中。感谢 Mark Shinwell、Damien Doligez 和 Xavier Leroy 的宝贵反馈和代码建议。

特别感谢社区中的所有 OCaml 用户和开发者对项目的持续支持和贡献。保持安全!

首字母缩略词

  • AMD:超微半导体
  • CI:持续集成
  • CTF:通用跟踪格式
  • DLAB:域本地分配缓冲区
  • DWARF:使用属性记录格式进行调试
  • ETL:提取转换加载
  • GC:垃圾收集器
  • OPAM:OCaml 包管理器
  • PR:拉取请求
  • UI:用户界面
  • URL:统一资源定位器
  • ZMQ:ZeroMQ