OCaml 多核 - 2020 年 8 月

欢迎阅读 2020 年 8 月的 OCaml 多核报告(由于 8 月份的放缓,延迟了几周)。此更新以及 以前的更新 由 @shakthimaan、@kayceesrk 和我共同整理。

现在有一些关于 OCaml 多核的演讲在网上免费提供

OCaml 多核项目在 2020 年 8 月取得了许多优化和性能改进

  • 有关 使用 pthreads 实现 systhreads 的 PR 仍在接受审查和改进。合并后,这将开启使用 OCaml 多核安装 dune 和其他包的可能性。
  • Domain 模块现在也正在 接受审查,以实现互斥锁和条件变量。
  • 工作已经开始实施 GC 安全点,以确保能够可靠地进行低延迟垃圾收集。

我们要特别感谢以下外部贡献者

  • Albin Coquereau 和 Guillaume Bury 为他们关于在沙箱环境中使用 dune.2.6.0 和 OCaml 多核 4.10.0 构建 Alt-Ergo.2.3.2 的评论和建议。
  • @Leonidas 帮助测试了使用 CoreAsync 的代码大小度量实现,并提供了代码审查变更。

非常欢迎您对使用我们的基准测试套件来调整项目做出的类似上述贡献。与之前的更新一样,我们首先介绍 OCaml 多核更新,然后介绍 Sandmark 基准测试项目的增强功能和错误修复。最后列出了上游 OCaml 的正在进行和已完成的任务,供您参考。

OCaml 多核

正在进行

  • ocaml-multicore/ocaml-multicore#381 使用 pthreads 重新实现 systhreads

    此 PR 在领域 API 的添加、与备份线程的交互方式的更改和错误修复方面取得了巨大进展。我们现在可以使用此 PR 为 OCaml 多核构建 dune.2.6.1utop,它已经可以进行审查了!

  • ocaml-multicore/ocaml-multicore#384 添加一个用于插入 nop 指令的原语

    引入了 nop 原语,用于识别指令序列的开头和结尾,以帮助调试低级代码。

  • ocaml-multicore/ocaml-multicore#390 互斥锁和条件变量的初始实现

    为 OCaml 多核运行时添加了对互斥锁变量和条件操作的支持的草案提案。

已完成

优化

  • ocaml-multicore/domainslib#16 parallel_for 实现的改进

    引入了分治方案来分配 parallel_for 中的工作,并且 chunk_size 成为一个参数,以提高在 8-16 个以上内核上的可扩展性。以下插图中的蓝色线显示了 Sandmark 中使用默认 chunk_size 以及此 PR 对一些基准测试的改进:OCaml-Domainslib-16-Illustration|465x500

  • ocaml-multicore/multicore-opam 对多核变体构建使用 -j%{jobs}%

    在多核变体的构建步骤中使用 -j%{jobs}% 将加快 opam 安装速度。

  • ocaml-multicore/ocaml-multicore#374 在次要收集时强制执行主要切片

    如果被阻塞的线程可能无法通过 handle_interrupt 服务次要收集器来推进主要 GC,则次要收集将需要调度主要收集。

  • ocaml-multicore/ocaml-multicore#378 在分配时扫描时保留空池

    通过在 pool_sweep 函数中使用 release_to_global_pool 标志,可以实现一项优化,以改善暂停时间并减少锁的数量,该标志将继续保留空池。

  • ocaml-multicore/ocaml-multicore#379 可中断的标记和扫描

    标记和扫描工作现在可以中断,因此即使一个领域正在执行大型任务,领域也可以进入停止世界的次要收集。例如,对于具有四个领域的二叉树基准测试,领域三中的主要工作(粉色)会阻止其他领域的进度,如事件日志所示。OCaml-Multicore-PR-379-Illustration-Before|539x500

    通过此补丁,我们可以观察到领域二和四中的主要工作在以下插图中取得进展:OCaml-Multicore-PR-379-Illustration-After|655x500

  • ocaml-multicore/ocaml-multicore#380 将 DLS 调用到 caml_domain_dls_get 标记为 @@noalloc

    caml_dls_get 被标记为 @@noalloc,以减少 C 调用的开销。

  • ocaml-multicore/ocaml-multicore#382 优化 caml_continuation_use_function

    通过使用 caml_domain_alone 和在 DEBUG 模式下使用 caml_gc_log,可以实现一些优化,从而为生成器示例带来 25% 的性能提升。

  • ocaml-multicore/ocaml-multicore#389 使用备份线程时避免持有 domain_lock

    通过更改备份线程逻辑来减少主 OCaml 线程的等待时间,而无需为 BT_IN_BLOCKING_SECTION 持有 domain_lock

杂项

基准测试

正在进行

  • ocaml-bench/sandmark#122 代码大小的度量

    基准测试的代码大小是 flambda 分支所需的度量之一。已创建了一个 PR,它现在会在基准测试结果的输出中输出 CAML 符号的计数,如下所示

    {"name":"knucleotide.", ... ,"codesize":276859.0, ...}
    
  • ocaml-bench/sandmark#169 在 Makefile 中添加 .json、pkg-config 和 m4 的 check_url

    在 Makefile 中定义了一个 check_url 目标,以确保 ocaml-versions/*.json 文件具有 URL 参数。此补丁还将 pkg-configm4 添加到 Ubuntu 依赖项中。

已完成

基准测试

  • ocaml-bench/sandmark#107 添加 Coq 基准测试

    来自 程序形式推理fraplib 库已 dunify 并包含在 Sandmark 中,用于 Coq 基准测试。

  • ocaml-bench/sandmark#151 进化算法并行基准测试

    进化算法并行基准测试现已添加到 Sandmark 中。

  • ocaml-bench/sandmark#152 LU 分解:并行随机数初始化

    LU 分解基准测试的随机数初始化现在具有并行性,使用 Domain.DLSRandom.State

  • ocaml-bench/sandmark#153 添加计算密集型 Coq 基准测试

    BasicSyntaxAbstractInterpretation Coq 文件执行大量次要 GC 和分配,并已作为基准测试添加到 Sandmark 中。

  • ocaml-bench/sandmark#155 进化算法的顺序版本

    顺序版本的算法用于与其各自的并行实现进行比较。Sandmark 中现在包含了 进化算法 的顺序实现。

  • ocaml-bench/sandmark#157 Minilight 多核:移植到 Task API 和 DLS 以用于随机状态

    Minilight 基准测试已移植到使用 Task API,并使用 Domain Local Storage 用于随机状态。速度提升如以下插图所示

    PR 157 Image

  • ocaml-bench/sandmark#164 对 multicore-numerical/game_of_life 进行调整

    现在可以配置生命游戏数值基准测试的 board_size,并且可以作为参数提供。

错误修复

  • ocaml-bench/sandmark#156 修复 Nbody 多核的计算

    Nbody 实现中对物体交互的计算进行了少量修复,并使用了局部 ref 变量以减少写入和缓存流量。

  • ocaml-bench/sandmark#158 修复 Jupyter 笔记本中 Grammatrix 的键错误

    通过在 multicore_parallel_run_config.json 文件中将值传递给 params,现已解决了 notebooks/parallel/parallel.ipynb 中的 键错误 问题。

杂项

  • ocaml-bench/sandmark#154 恢复 PARAMWRAPPER 更改

    撤消 Makefile 中并行基准测试运行的 PARAMWRAPPER 配置,因为它们在顺序执行中不需要。

  • ocaml-bench/sandmark#160 为 alt-ergo 沙箱构建指定前缀和 libdir

    alt-ergo 库和解析器需要在沙箱环境中构建时,使用 configure 指定 prefixlibdir。 初始讨论可在 OCamlPro/alt-ergo#351 找到。

  • ocaml-bench/sandmark#162 避免安装多核运行中未使用的包

    Makefile 中的 PACKAGES 变量已简化为仅包含构建 Sandmark 所需的那些依赖包。

  • ocaml-bench/sandmark#163 更新到 domainslib 0.2.2 并使用默认的 chunk_size

    domainslib 依赖包已更新为使用 0.2.2 版本,并且各种基准测试的 chunk_size 使用 num_tasks/num_domains 作为默认值。

OCaml

进行中

  • ocaml/ocaml#9756 垃圾收集器颜色更改

    此 PR 通过消除垃圾收集器 (GC) 颜色方案中对灰色颜色的需求,可以与多核 OCaml 主收集器一起使用。

已完成

  • ocaml/ocaml#9722 基于 EINTR 的信号,再次

    此补丁提供了一种新的实现来解决一系列锁定、信号处理和错误检查问题。

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

缩略词

  • API: 应用程序编程接口
  • DLS: 域本地存储
  • GC: 垃圾收集器
  • OPAM: OCaml 包管理器
  • LU: 下三角-上三角 (分解)
  • PR: 拉取请求