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 将它们分开。
在上图中,当主线程正在等待条件变量时,备份线程处于活动状态。
基准测试
正在进行
-
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 删除主干的
Base
、Stdio
orun 依赖项Sandmark 中的
orun
源代码已更新为删除对Base
和Stdio
的依赖关系。它们已被Stdlib
、List
、String
和Str
中的函数替换。 -
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 套件中现有的一些基准测试确实溢出了标记栈,如下图所示,并且更改对性能的影响很小。
一如既往,我们要感谢社区中所有 OCaml 开发人员和用户对项目的持续支持和贡献。祝好!
缩写
- ARM:高级精简指令集机器
- BFS:广度优先搜索
- DEC:域执行上下文
- GC:垃圾收集器
- JSON:JavaScript 对象表示法
- NUMA:非一致性内存访问
- OPAM:OCaml 包管理器
- OS:操作系统
- PR:拉取请求
- RISC-V:精简指令集计算 - V
- SSSP:单源最短路径