OCaml 多核 - 2020年11月
欢迎阅读 2020 年 11 月的多核 OCaml 报告!此更新以及之前的更新由 @shakthimaan、@kayceesrk 和 @avsm 共同编制。
多核 OCaml:自上个月合并了对 systhreads 的支持以来,许多生态系统包都能够编译。我们一直在对 opam 仓库进行批量构建(使用专门的opam-health-check 实例),以解决剩余的构建错误。大多数问题都与使用与垃圾回收器相关的 C 存根的包有关,尽管我们确实发现了一些实际的多核错误(与使用 dynlink 时线程机制相关)。详细信息请参见下面的“生态系统”部分。我们还花费大量时间优化多核编译器中的堆栈规则,作为编写关于效果系统草案论文的一部分(稍后将提供更多详细信息)。
上游 OCaml:4.12.0alpha2 版本现已发布,其中包含动态裸指针检查器,以帮助确保您的代码仅使用已打包的外部指针。请在您的代码库上运行它以帮助准备。对于 OCaml 4.13(当前的 trunk
)分支,我们举行了一次完整的 OCaml 开发者会议,并在会上确定了要提交到上游的工作列表。主要工作是关于GC 安全点,而不是缓存次要堆指针,此后,运行时域支持具有上游所有必要的先决条件。这两个 PR 都对性能非常敏感,因此正在进行大量的图表分析(尽管不可抑制的 @stedolan 提供了一次大规模的顺路优化)。
Sandmark 基准测试:Lockfree 和 Graph500 基准测试分别已添加到 Sandmark 并进行了更新,我们继续致力于工具方面的工作。还在 AMD、ARM 和 PowerPC 硬件上进行了基准测试,以研究编译器的性能。参考标准 OCaml,安全点 PR 现已提交审查。
与之前的更新一样,首先列出多核 OCaml 任务,然后是 Sandmark 基准测试套件的进度。最后,提到上游 OCaml 相关工作以供参考。
多核 OCaml
正在进行
-
ocaml-multicore/ocaml-multicore#439 Systhread 生命周期工作
改进 systhreads 的初始化以进行通用资源处理,并释放描述符和堆栈。现在在运行时存在一个新的域终止挂钩。
-
ocaml-multicore/ocaml-multicore#440
ocamlfind ocamldep
在无效果语法分支中挂起nocrypto
包无法为多核 OCaml 无效果语法分支构建,并且 ocamlfind 持续循环。已创建了一个最小的测试示例来重现此问题。 -
ocaml-multicore/ocaml-multicore#443 次要堆分配启动成本
一个问题,用于跟踪对 OCaml 多核程序的大型次要堆大小影响的持续调查。问题中提供了各种次要堆大小的顺序和并行执行运行结果。
-
ocaml-multicore/ocaml-multicore#446 在次要收集结束时收集 GC 统计信息
目标是通过使用并行_次要_gc 模式中次要收集期间存在的屏障来移除 GC 统计信息收集中双缓冲的使用。正如插图所示,与标准 OCaml 相比,基准测试运行速度没有明显下降。
已完成
上游
-
ocaml-multicore/ocaml-multicore#426 替换全局根实现
此 PR 将现有的全局根实现替换为 OCaml 的
globroots
,其中实现围绕跳表放置锁。将来,将删除Caml_root
的使用及其在 globroots 中的使用。 -
ocaml-multicore/ocaml-multicore#427 垃圾回收器颜色更改回传
主收集器的垃圾回收器颜色更改 PR 已从 trunk 回传到多核 OCaml。这包括对
mark_stack_push
的优化,mark_entry
不包含end
,并且caml_shrink_mark_stack
已从 trunk 移植过来。 -
ocaml-multicore/ocaml-multicore#432 删除堆栈切换上的 caml_context push/pop
删除堆栈切换上
caml_context
push/pop 使用的动机是为了使实现更容易理解,并更接近上游 OCaml。
堆栈改进
-
修复扫描堆栈上的堆栈溢出#431 修复问题 421:扫描堆栈上的堆栈溢出
caml_scan_stack
现在使用 while 循环来避免一个堆栈溢出极端情况,即存在深度嵌套的纤维。 -
ocaml-multicore/ocaml-multicore#434 用于效果堆栈切换的 DWARF 修复
PR 提供了对
runtime/amd64.S
的修复,这些修复是在使用 DWARF 验证器时发现的。该补丁还清理了已注释掉的死代码,并在我们执行caml_free_stack
incaml_runstack
时更新了 DWARF 信息。 -
ocaml-multicore/ocaml-multicore#435 标记堆栈溢出回传
标记堆栈溢出实现已更新,使其更接近 trunk OCaml。首先将池添加到跳表中以避免任何重复,并在主要周期中稍后标记
pools_to_rescan
中的池。下图显示了带有标记堆栈溢出的finalise
基准测试时间差的结果
-
ocaml-multicore/ocaml-multicore#437 使用 continue 切换堆栈时避免分配 C 调用
caml_continuation_use
已更新为使用caml_continuation_use_noexc
,并且它不会引发异常。不再需要分配 Ccaml_c_call
来调用caml_continuation_use_noexc
。 -
ocaml-multicore/ocaml-multicore#441 整理并添加更多关于 amd64.S 中 caml_runstack 的注释
PR 添加了关于如何切换堆栈的注释,并删除了 x86 汇编程序中不必要的指令。
-
ocaml-multicore/ocaml-multicore#442 纤维堆栈缓存 (v2)
添加纤维堆栈的堆栈缓存,这也修复了测试套件中的错误(DEBUG memset,初始化顺序)。我们在管理堆栈缓存时避免了
struct stack_info
的间接寻址,并有效地计算了给定堆栈大小的缓存空闲列表存储桶。
生态系统
-
ocaml-multicore/lockfree#5 删除 Kcas 依赖项
Kcas.Wl
模块现已替换为多核标准库中提供的 Atomic 模块。指数退避是用Domain.Sync.cpu_relax
实现的。 -
ocaml-multicore/domainslib#21 指向新的存储库 URL
感谢 Sora Morimoto (@smorimoto) 提供了更新 URL 为正确的 ocaml-multicore 存储库的补丁。
-
ocaml-multicore/multicore-opam#40 添加多核 Merlin 和 dot-merlin-reader
一个用于 merlin 和 dot-merlin-reader 的补丁,用于与多核 OCaml 4.10 协同工作。
-
ocaml-multicore/ocaml-multicore#403 尝试在多核上构建 Tezos 时出现分段错误
替换全局根实现的最新修复以及修复 STW 中断竞争到无效果语法分支已解决了此问题。
编译器修复
-
ocaml-multicore/ocaml-multicore#438 允许 C++ 使用 caml/camlatomic.h
包含 extern "C" 头文件以允许 C++ 使用 caml/camlatomic.h 构建 ubpf.0.1。
-
ocaml-multicore/ocaml-multicore#447 domain_state.h:使用 -pedantic 时删除警告
一个使用
CAML_STATIC_ASSERT
检查 domain_state.h 中caml_domain_state
大小的修复程序,以在使用 -pedantic 时删除警告。 -
ocaml-multicore/ocaml-multicore#449 在 C++ 内部良好使用 stdatomic.h
使用 extern C++ 声明更新
caml/camlatomic.h
以在 C++ 内部使用它。这构建了 upbf.0.1 和 libsvm.0.10.0 包。
其他
-
ocaml-multicore/ocaml-multicore#422 简化次要堆配置逻辑和屏蔽
引入了
Minor_heap_max
大小以保留次要堆区域,并使用边界检查依靠Is_young
。可以使用 OCAMLRUNPARAM 环境变量覆盖Minor_heap_max
参数。此实现方法旨在使用域本地分配缓冲区。 -
ocaml-multicore/ocaml-multicore#429 修复 STW 中断竞争
修复
caml_try_run_on_all_domains_with_spin_work
中的 STW 中断竞争。现在在中断其他域后初始化stw_request
的enter_spin_callback
和enter_spin_data
字段。 -
ocaml-multicore/ocaml-multicore#430 添加一个测试来练习存储的延续和 GC
PR 添加了对 GC 与存储的、克隆的和丢弃的延续之间的交互的测试覆盖,以练习次要和主要收集器。
-
ocaml-multicore/ocaml-multicore#444 将分支 'parallel_minor_gc' 合并到 'no-effect-syntax'
parallel_minor_gc
分支已合并到no-effect-syntax
分支,我们将尝试使no-effect-syntax
分支与最新更改保持同步。
基准测试
正在进行
-
ocaml-bench/sandmark#196 基于标签过滤基准测试
一项增强功能,朝着通用实现方向发展,以根据标签过滤基准测试,而不是依赖于自定义目标,例如 _macro.json 或 _ci.json。
-
ocaml-bench/sandmark#191 使 parallel.ipynb 笔记本交互化
parallel.ipynb 笔记本已实现交互化,并添加了下拉菜单以选择要分析的 .bench 文件。笔记本自述文件已与顶层自述文件合并。一个示例 4.10.0.orunchrt.bench 以及 *pausetimes_multicore.bench 文件已移动到 test artifacts/ 文件夹,供用户测试。
-
我们正在继续测试使用
opam-compiler
切换环境来执行 Sandmark 基准测试套件。我们已能够构建依赖项orun
和rungen
、OCurrent
管道及其依赖项,以及 ocaml-multicore:no-effect-syntax 分支的ocaml-ci
。我们希望能够使用所需的 OCaml 工具和生态系统,最终实现 2.0 版本。
已完成
-
ocaml-bench/sandmark#179 [RFC] 基于运行时间对基准测试进行分类
已解决 基准测试分类 的 PR,该 PR 现在根据基准测试的运行时间对其进行分类。
lt_1s
:运行时间少于 1 秒的基准测试。lt_10s
:运行时间至少 1 秒,但少于 10 秒的基准测试。10s_100s
:运行时间至少 10 秒,但少于 100 秒的基准测试。gt_100s
:运行时间至少 100 秒的基准测试。
-
ocaml-bench/sandmark#189 添加对 JSON 配置文件包装器中环境的支持
现在可以在运行时执行基准测试时,将 OCAMLRUNPARAM 参数作为环境变量传递。环境变量可以在
run_config.json
文件中指定,如下所示。{ "name": "orun_2M", "environment": "OCAMLRUNPARAM='s=2M'", "command": "orun -o %{output} -- taskset --cpu-list 5 %{command}" }
-
ocaml-bench/sandmark#183 使用 crout_decomposition 名称作为数值分析基准测试
numerical-analysis/lu_decomposition.ml
基准测试现已重命名为crout_decomposition.ml
,以避免命名混淆,因为 Sandmark 中有几个 LU 分解基准测试。 -
ocaml-bench/sandmark#190 将主干版本提升到 4.13.0
Sandmark ocaml-versions/ 中的主干版本现已更新为使用
4.13.0+trunk.json
。 -
ocaml-bench/sandmark#192 GraphSEQ 已修正
已为 Graph500 基准测试提供了 Kronecker 生成器的细微修复。
-
ocaml-bench/sandmark#194 无锁基准测试
串行和并行实现的无锁基准测试现已包含在 Sandmark 中,并使用
lockfree_bench
标签。时间和加速效果图如下所示。
OCaml
正在进行
-
ocaml/ocaml#9876 不要在处理器寄存器中缓存 young_limit
正在使用 Sandmark 基准测试运行来评估在寄存器中删除
young_limit
缓存的效果,以测试对 ARM64、PowerPC 和 RISC-V 端口硬件的影响。 -
ocaml/ocaml#9934 用于清除操作的预取优化
该 PR 包括对
sweep_slice
的优化,以使用预取,并在 GC 期间减少缓存未命中。归一化运行时间图如下所示。
-
4.11 分支的 AMD64 的安全点实现草案,通过向 Mach 添加新的
Ipoll
操作来实现。下面给出了 AMD Zen2 机器上的基准测试结果。
非常感谢所有 OCaml 用户和开发人员持续的支持和对项目的贡献。
缩写
- ARM:高级精简指令集机器
- DWARF:带属性记录格式的调试
- GC:垃圾回收器
- JSON:JavaScript 对象表示法
- OPAM:OCaml 包管理器
- PR:拉取请求
- PR:拉取请求
- RFC:征求意见
- RISC-V:精简指令集计算 - V
- STW:停止世界
- URL:统一资源定位符