OCaml 多核 - 2021年2月

欢迎阅读 2021 年 2 月的 多核 OCaml 月度报告。此更新以及 先前更新 由我、@kayceesrk 和 @shakthimaan 共同编制。2 月份,我们主要关注多核树的稳定性,因为解锁生态系统构建和运行批量 CI 为我们提供了大量问题,帮助我们追查极端情况下的问题。将下一批更改上游到 OCaml 4.13 的工作也取得了很大进展。

总的来说,我们仍然有望在下一个 OCaml 版本 (4.13.0) 发布后拥有一个支持并行的多核运行时 (版本 5.0),尽管确切的发布细节尚未在核心 OCaml 开发人员会议上得到批准。令人兴奋的是,我们在并发方面也取得了重大进展,下面详细介绍了一篇关于该主题的新论文。

4.12.0:发布了包含与多核相关的更改

OCaml 4.12.0 已发布,其中包含大量内部更改 多核 OCaml 所需,例如 GC 颜色处理、页面表的移除以及堆表示的修改。

从开发人员的角度来看,现在有一个名为 nnpchecker 的新配置选项,它可以动态地为运行时添加工具,以帮助您发现绑定中未装箱的 C 指针的使用。这在 针对 4.10 的早期版本 中有描述,但现在也已在 opam 存储库 CI 上上线。从现在开始,**新的 opam 包提交如果在您的 opam 包测试套件中检测到裸指针,将会发出测试失败的警告**。请尝试在您的 opam 包中包含测试以获得此功能的好处!

下面的屏幕截图显示了它在 LLVM 包上的工作情况(目前已知该包存在裸指针)。

image|690x458, 75%

4.13~dev:上游进展

我们针对 4.13 版本的 PR 队列主要集中在“安全点”的集成上,这些安全点提供了更强的保证,即即使应用程序逻辑没有定期分配内存,OCaml mutator 也会定期轮询垃圾收集器。这项工作几乎 三年前 就开始在多核 OCaml 树中进行,现在正在 上游 OCaml 中进行代码审查——请务必提供任何关于该 PR 的性能或代码大小测试。

除此之外,团队还在处理其他各种先决条件,例如多核安全的 Lazy、内存模型的实现(在 这篇 PLDI 18 论文 中解释)以及使 ephemeron API 更适合并行处理。目前尚不清楚其中哪些将进入 4.13,哪些将直接进入 5.0 树。

OCaml 5.0 之后:并发和纤程

我们很高兴分享一篇关于 “将 Effect 处理器改造到 OCaml 上” 的新预印本,它延续了我们的“改造”系列,涵盖了在 OCaml 代码中表达交错所需的并发元素。该论文已被有条件地接受在 PLDI 2021(虚拟)上发表,我们目前正在撰写最终版本。欢迎任何反馈意见,请发送给 @kayceesrk 或我本人。摘要如下

Effect 处理器作为一种用于模块化编程的机制,其势头越来越强劲,并支持用户定义的 Effect。Effect 处理器允许以可组合的方式表达非局部控制流机制,例如生成器、async/await、轻量级线程和协程。我们提出了一个设计,并评估了为 OCaml(一种工业级多范式编程语言)实现完整高效的 Effect 处理器。我们的实现力求保持现有 OCaml 代码的向后兼容性和性能特征。将 Effect 处理器改造到 OCaml 上极具挑战性,因为 OCaml 目前没有其他非局部控制流机制,除了异常。我们为 OCaml 实现的 Effect 处理器:(i) 对不使用 Effect 处理器的代码产生的开销可以忽略不计;(ii) 保持与检查堆栈的程序分析工具的兼容性;(iii) 对使用 Effect 处理器的新代码效率很高。

我们非常重视确保 OCaml 原生代码实现(尤其是调试和回溯)的现有良好特性在我们的拟议并发扩展中得以保持。与对 OCaml 进行的任何此类重大更改一样,本文内容应被视为研究级,直至在未来的核心 OCaml 开发人员会议上得到批准。但请务必尝试使用纤程和 Effect,并向我们提供反馈!我们目前正在开发一个高性能的 直接风格 IO 堆栈,其早期性能数据非常有希望。

如果您想了解更多关于 Effect 的信息,@kayceesrk 在 Lambda Days 2021 上做了一个关于Effective Programming 的演讲(演示文稿幻灯片)。

使用 Sandmark 进行性能测量

@shakthimaan 在社区演讲中介绍了 Sandmark 2.0 的即将推出的功能及其未来的路线图。该 幻灯片 已发布到网上,请向他发送您可能对性能基准测试有任何疑问的反馈。Sandmark 2.0 -alpha 分支针对各种目标和构建标签完成了完整的回归测试,我们继续开发 2.0 版本的新功能。然后进入细节!首先列出多核 OCaml 更新,然后列出 Sandmark 基准测试项目的各种正在进行和已完成的任务。最后,列出正在进行的上游 OCaml 工作以供参考。

多核 OCaml

正在进行

生态系统

  • ocaml-multicore/multicore-opam#46 与多核兼容的 ocaml-migrate-parsetree.2.1.0

    一个补丁,用于使 ocaml-migrate-parsetree 源代码使用 Effect 语法。现在可以使用多核 OCaml parallel_minor_gc 很好地构建。

  • ocaml-multicore/multicore-opam#47 与多核兼容的 ppxlib

    Effect 语法现已添加到 ppxlib 中,现在与多核 OCaml 兼容。

改进

  • ocaml-multicore/ocaml-multicore#474 修复重标记以确保与并行域安全

    一个修复另一个域拥有的池重标记问题的草案提案。该解决方案旨在将池的重标记移动到拥有该池的域。

  • ocaml-multicore/ocaml-multicore#477 将 TLS 区域移动到专用内存空间

    该 PR 更改了我们分配单个域的 TLS 的方式。目前的实现对于域本地分配缓冲区而言并非最佳,因此该补丁将 TLS 区域移动到其自身分配的内存空间。

  • ocaml-multicore/ocaml-multicore#480 从 STW API 中移除 leave_when_done 及其相关函数

    通过从 caml_try_run_on_all_domains*stw_request 中移除屏障来清理 stw_request.leave_when_done

其他

  • ocaml-multicore/ocaml-multicore#466 修复在另一个域中重标记池且该域分配时发生的损坏

    正在调查 parallel/domain_parallel_spawn_burn 的字节码测试失败。建议每个域都有一个重标记队列,以及一个全局重标记队列来保存任何孤立池或无法排队到域的工作。

  • ocaml-multicore/ocaml-multicore#468 使用多个域时,终结器导致段错误

    已提交一个测试用例,其中终结器在使用多个域时会导致段错误。

  • ocaml-multicore/ocaml-multicore#471 Unix.fork 失败并显示“unlock: Operation not permitted”

    fork 实现上的非阻塞部分在解锁期间导致致命错误,并显示“operation not permitted”消息。opam-ci 已报告此问题。

  • ocaml-multicore/ocaml-multicore#473 构建 musl 需要动态链接 execinfo

    Haz 尝试使用 musl 构建多核 OCaml。它失败了,因为需要链接外部 libexecinfo。

  • ocaml-multicore/ocaml-multicore#475 不要重用字节码指令的操作码

    Hugo Heuzard 提出一个问题,关于扩展现有操作码和附加指令,而不是重用操作码并在多核 OCaml 中移动它们。

  • ocaml-multicore/ocaml-multicore#479 Continuation_already_taken 使顶级崩溃

    针对 4.10.0+multicore 在 x86-64 上的迭代器到生成器的练习报告了一个 continuation already taken 段错误崩溃。

已完成

全局根

  • ocaml-multicore/ocaml-multicore#472 主 GC:从一个域扫描全局根

    作为并行化全局根扫描的第一步,提供了一个补丁,该补丁在主循环中仅从一个域扫描全局根。下面显示了应用该补丁后的并行基准测试结果

PR 472 Parallel Benchmarks|690x464

  • ocaml-multicore/ocaml-multicore#476 全局根并行测试

    现在添加了 globroots_parallel_single.mlglobroots_parallel_multiple.ml 测试,以检查全局根与域生命周期的交互。

CI

  • ocaml-multicore/ocaml-multicore#478 移除 .travis.yml

    我们现在已移除对 Travis 的 CI 使用,因为我们现在使用 GitHub Actions。

  • 我们现在引入了标签,您可以在为多核 OCaml 报告错误时使用这些标签。当前标签集列在 https://github.com/ocaml-multicore/ocaml-multicore/labels 上。

其他

基准测试

正在进行

修复

  • ocaml-bench/sandmark#208 修复 simple-tests/capi 的参数

    现在已正确传递到 simple-tests/capi 基准测试的参数,并且它们可以正常构建和执行。可以使用以下命令验证这一点

    $ TAG='"lt_1s"' make run_config_filtered.json
    $ RUN_CONFIG_JSON=run_config_filtered.json make ocaml-versions/4.10.0+multicore.bench
    
  • ocaml-bench/sandmark#209 使用规则目标 kronecker.txt 并从 macro_bench 中移除

    Graph500seq 基准测试已更新,在运行kernel2kernel3 之前使用目标规则构建 kronecker.txt。这组基准测试已从 macro_bench 标签中移除。

其他

  • ocaml-bench/sandmark#205 [RFC] 对基准测试进行分类和分组

    一份草案提案,建议根据 Sandmark 基准测试的使用和应用将其分类为一系列算法。建议的列表包括 libraryformalnumericalgraph 等。

  • ocaml/opam-repository#18203 [新版本] orun (0.0.1)

    正在进行的工作是在 opam.ocaml.org 上发布 orun 包。还创建了一个新的 conf-libdw 包来处理依赖项。

  • Sandmark 2.0 -alpha 分支现在包含了当前 Sandmark 主分支中的所有基准测试目标,并且我们一直在对各种标签进行回归构建。所需的依赖包也已添加到相应的目标基准测试中。

已完成

  • ocaml/opam-repository#18176 [新版本] rungen (0.0.1)

    rungen 包已从 Sandmark 2.0 中移除,现在可在 opam.ocaml.org 上获得。

OCaml

正在进行

  • ocaml/ocaml#10039 安全点

    安全点 PR 实现了序言省略算法,现在已重新整理到主干。省略优化和叶子函数优化的效果减少了轮询次数,如下所示

PR 10039 Polls from Leaf Functions |690x326

感谢社区中所有 OCaml 用户和开发者对项目的贡献和支持!

缩略词

  • API:应用程序编程接口
  • CI:持续集成
  • DLAB:域本地分配缓冲区
  • GC:垃圾回收器
  • OPAM:OCaml 包管理器
  • PLDI:编程语言设计与实现
  • PR:拉取请求
  • RFC:征求意见稿
  • STW:停止世界
  • TLS:线程本地存储