OCaml 多核 - 2020年9月

多核 OCaml:2020年9月

欢迎阅读 2020年9月的多核 OCaml 报告!此更新以及之前的每月更新由@shakthimaan、@kayceesrk 和@avsm 共同编写。

本月的大新闻是systhreads 兼容性支持 PR 已合并,这意味着 Dune(以及其他 Thread 模块的用户)可以开箱即用地编译。您现在可以使用新的 opam compiler 插件方便地编译多核 OCaml 分支(查看公告

opam update
opam compiler create "ocaml-multicore/ocaml-multicore:no-effect-syntax"
eval $(opam env)

这选择了省略实验性 effect 语法的多核 OCaml 分支,因此可以与现有的 ppx 生态系统一起使用。最后,使用 opam 安装生态系统包并看到它们开箱即用非常有趣。线程兼容性支持仍然存在一些粗糙的边缘(主要是在 C 兼容层,例如在 GC 中注册外部 C 线程),但这些将在未来几周内解决。我们希望听到您在 opam 宇宙中遇到的任何构建失败:请在 https://github.com/ocaml-multicore/ocaml-multicore/issues 上报告它们

9 月份还完成了一些对多核 OCaml GC 和 Sandmark 基准测试项目的性能改进

  • 我们现在已将来自 Graph500 基准测试的Kronecker 实现 包含到 Sandmark 中
  • 正在进行n-皇后 基准测试的添加
  • 基准测试运行现在提供 OCaml 符号的计数作为代码大小指标
  • 使用多核 OCaml 构建 Tezos 的工作以及与 Sandmark 基准测试套件的集成也已开始。

我们还开始努力移植 Lwt 以利用 Lwt_preemptive 的并行性。代码示例 和测试运行已经执行,Sudha 撰写了一篇介绍性博文 介绍她的早期结果。请注意,这项工作不会改变 Lwt 的核心行为(一个协作式期货框架,在 bind 调用之间没有上下文切换),但允许通过对后台抢占式线程的显式调用实现并行性。

关于向上游 OCaml 的努力,4.12 版本的冻结时间将比往常早,在 10 月份,因此我们完成了提交最后垃圾收集器颜色更改 的工作,并计划在 OCaml 4.13 中进行可靠安全点的相关工作。4.12 中已经包含了许多运行时更改,因此当 4.12 的候选版本发布时,我们将发布测试请求。

接下来是 PR 的详细信息。与之前的更新一样,首先列出多核 OCaml 更新,然后是 Sandmark 基准测试项目的增强功能。最后提及了上游 OCaml 的正在进行和已完成的更新,以供参考。

多核 OCaml

正在进行

  • ocaml-multicore/domainslib#17 使用互斥锁和条件变量实现通道

    lib/chan.ml 源代码已更新为使用互斥锁和条件变量实现通道,并为其添加了一个 LU_decomposition_multicore.exe 测试。

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

    此 PR 正在积极审查在多核 OCaml 中使用 pthreads。它引入了域执行上下文 (DEC),允许多个线程在域之上运行。

  • ocaml-multicore/ocaml-multicore#394 轮询放置的更改

    轮询放置在函数的开头和循环的后边缘进行,而不是使用 Feely 算法。这是一个正在进行中的工作。

  • ocaml-multicore/ocaml-multicore#401 不要递归处理中断

    引入了一个域局部变量以防止递归处理中断。

  • ocaml-multicore/ocaml-multicore#402 将 handle_gc_interrupt 分割为处理远程和轮询部分

    引入了一个 caml_poll_gc_work,其中包含之前在 caml_handle_gc_interrupt 中完成的 GC 工作信息。这有助于 stw_handler 对轮询进行调用,而不是处理服务中断,因为它可能导致不必要的递归。

  • ocaml-multicore/ocaml-multicore#403 在没有 effect 语法的多核 4.10.0 上构建 Tezos 时出现分段错误

    这是一个正在进行的调查,以了解 Tezos 中的 tezos-embedded-protocol-packer 包在使用多核 OCaml 构建时为何会导致分段错误。

已完成

Domainslib

  • ocaml-multicore/domainslib#19 使用互斥锁和条件变量进行更细粒度的通道信号传递

    对互斥锁和条件变量使用细粒度锁定有助于提高大型内核的性能,而不是对所有信号使用单个互斥锁。

多核 OPAM

  • ocaml-multicore/multicore-opam#31 为多核 OCaml 打补丁 dune.2.7.1

    已添加 dune.2.7.1 的 opam 文件以及对 bootstrap.ml 的补丁,使其适用于多核 OCaml,感谢 Chaitanya Koparkar。

  • ocaml-multicore/multicore-opam#32 将 ocamlfind-secondary 依赖项添加到 dune

    dune 的安装需要 ocamlfind-secondary 作为 dune.2.7.1 的依赖项,并已添加到 OPAM 文件中。

多核 OCaml

  • ocaml-multicore/ocaml-multicore#395 将所有旋转迁移到 SPIN_WAIT 并在 SPIN_WAIT 中使用 usleep

    PR 为所有繁忙旋转等待循环提供了 SPIN_WAIT 宏,并在繁忙等待时使用 caml_plat_spin_wait。这确保在代码的不同位置使用相同的旋转策略。

  • ocaml-multicore/ocaml-multicore#397 备份线程信号的放松

    修改了在离开阻塞部分时从 mutator 线程向备份线程发送信号的方式。它减少了重新进入 OCaml 时潜在的操作系统调度。

  • ocaml-multicore/ocaml-multicore#400 备份线程的事件日志解复用

    备份线程中的事件发出与主线程相同的进程 ID,此 PR 将它们分开。

PR 400|690x246

在上图中,当主线程正在等待条件变量时,备份线程处于活动状态。

基准测试

正在进行

  • ocaml-bench/sandmark#159 实现一种描述 tasklet cpulist 的更好方法

    当我们提供多个域时,我们需要一种更简洁的方法来获取基准测试运行的核心任务集列表。我们应该能够指定超线程核心、要使用的 NUMA 区域以及并行基准测试要使用的特定核心。

  • ocaml-bench/sandmark#173 将 nqueens 基准测试添加到多核数值

    经典的 n 皇后 基准测试的草稿版本已添加到 Sandmark 中以供审查。这包括单核和多核实现。

已完成

  • ocaml-bench/ocaml_bench_scripts#11 添加对配置选项和 OCAMLRUNPARAM 的支持

    ocaml_bench_scripts 已更新为支持在 Sandmark 中构建和运行基准测试时传递 configure 选项和 OCAMLRUNPARAM。

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

    从基准测试生成的输出 .bench JSON 文件现在包含 CAML 符号数量的代码大小指标。下面显示了一个基准测试输出示例

    {"name":"knucleotide.", ... ,"codesize":276859.0, ...}
    

    下面给出了一些基准测试的代码大小计数

    | Benchmark  |   Count   |
    |------------|-----------|
    | alt-ergo   | 2_822_040 |
    | coqc       | 5_869_305 |
    | cpdf       | 1_131_376 |
    | nbody.exe  |   276_710 |
    | stress.exe |    84_061 |
    | fft.exe    |    38_914 |
    
  • ocaml-bench/sandmark#170 Graph500 SEQ

    现在已将带有 Kronecker 图生成器的 Graph500 基准测试添加到 Sandmark 中。生成器构建三个内核用于图构建、广度优先搜索和单源最短路径。

  • ocaml-bench/sandmark#172 删除主干的 BaseStdio orun 依赖项

    Sandmark 中的 orun 源代码已更新为删除对 BaseStdio 的依赖关系。它们已被 StdlibListStringStr 中的函数替换。

  • ocaml-bench/sandmark#174 清理我们对 chrt 的 sudo 使用

    已从 Makefile 中删除 sudo 用于运行并行基准测试,以避免创建需要 root 权限才能访问的输出文件和目录。使用 RUN_BENCH_TARGET=run_orunchrt 将使用 chrt -r 1 执行基准测试。用户可以使用以下命令为 chrt 二进制文件授予权限

    $ sudo setcap cap_sys_nice=ep /usr/bin/chrt
    

OCaml

正在进行

  • ocaml/ocaml#9876 不要在处理器寄存器中缓存 young_limit

    PR 从 ARM64、PowerPC 和 RISC-V 端口的寄存器中删除了 young_limit 的缓存,因为它在多核 OCaml 中轮询信号和域间通信期间存在问题。

已完成

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

    垃圾收集器中的灰色方案已被删除,以方便与多核 OCaml 收集器合并。Sandmark 套件中现有的一些基准测试确实溢出了标记栈,如下图所示,并且更改对性能的影响很小。

PR-9756|690x495

一如既往,我们要感谢社区中所有 OCaml 开发人员和用户对项目的持续支持和贡献。祝好!

缩写

  • ARM:高级精简指令集机器
  • BFS:广度优先搜索
  • DEC:域执行上下文
  • GC:垃圾收集器
  • JSON:JavaScript 对象表示法
  • NUMA:非一致性内存访问
  • OPAM:OCaml 包管理器
  • OS:操作系统
  • PR:拉取请求
  • RISC-V:精简指令集计算 - V
  • SSSP:单源最短路径