OCaml 多核 - 2020 年 10 月
欢迎来到 2020 年 10 月的多核 OCaml 报告,由 @shakthimaan、@kayceesrk 以及我本人共同编写。[之前的每月 (https://discuss.ocaml.org/tag/multicore-monthly) 更新也可供您阅读。
OCaml 4.12.0-dev: 上游 OCaml 树已为 4.12 版本分支,并且 OCaml 就绪团队 正在努力与生态系统一起稳定它。4.12.0 开发分支在多核支持方面取得了重大进展,特别是裸指针的运行时处理。该版本将附带一个用于裸指针的动态检查器,您可以使用它来验证自己的代码库是否干净,因为这将是 OCaml 5.0 和多核兼容性的先决条件。这可以通过 --enable-naked-pointers-checker
配置选项激活。
与上游和多核树的融合: 多核 OCaml 树已经看到了显著的鲁棒性改进,因为我们已经将我们的树与上游 OCaml 融合在一起(现在上游架构更改已与多核的要求同步)。特别是,多核中对全局 C 根的处理现在要好得多,因为它使用上游 OCaml 方案,并且 GC 颜色方案也与上游 OCaml 的完全匹配。这意味着来自 opam
的社区库在使用多核 OCaml 构建时(使用 no-effects-syntax
分支)越来越好地工作。
功能: 多核 OCaml 现在还使用域本地分配缓冲区来简化其内部结构。我们现在还致力于对 IO 子系统进行基准测试,并为 Lwt 并发库添加了对 CPU 并行的支持,以及使用多核 OCaml、Lwt 和 httpaf 在 http-effects 库中刷新新的基于异步效果的 IO (aeio)。
基准测试: Sandmark 基准测试套件具有额外的配置选项,并且该项目中有新的提议尽可能地利用 OCaml 工具和生态系统。
与之前的更新一样,首先列出正在进行的和已完成的多核 OCaml 任务,然后是针对 Sandmark 基准测试套件的改进。最后,提到了与上游 OCaml 相关的作品,供您参考。
多核 OCaml
正在进行
-
ocaml-multicore/ocaml-multicore#422 简化次要堆配置逻辑和掩码
该 PR 是使用域本地分配缓冲区的一步。
Minor_heap_max
大小用于保留次要堆区域,Is_young
用于依赖边界检查。Minor_heap_max
可以使用 OCAMLRUNPARAM 环境变量覆盖。 -
ocaml-multicore/ocaml-multicore#426 替换全局根实现
一项努力旨在替换现有的全局根实现,使其与 OCaml 的
globroots
保持一致。目标是还拥有一个每个域的跳过列表,以及一个域终止时的全局孤儿。 -
ocaml-multicore/ocaml-multiore#427 垃圾收集器颜色更改回退
主要收集器中的 垃圾收集器颜色方案更改 现在已回退到多核 OCaml。
mark_entry
不包含end
,mark_stack_push
更接近于主干,并且caml_shrink_mark_stack
已从主干中移植。 -
ocaml-multicore/ocaml-multicore#429 修复 STW 中断竞争
该 PR 中修复了
caml_try_run_on_all_domains_with_spin_work
中的 STW 中断竞争,其中stw_request
的enter_spin_callback
和enter_spin_data
字段在中断其他域后进行初始化。
已完成
Systhreads 支持
-
ocaml-multicore/ocaml-multicore#381 使用 pthreads 重新实现 Systhreads(域执行上下文)
使用 pthreads 重新实现 Systhreads 已完成用于多核 OCaml。引入了域执行上下文 (DEC),它允许多个线程在域之上运行。
-
ocaml-multicore/ocaml-multicore#410 systhreads:
caml_c_thread_register
和caml_c_thread_unregister
caml_c_thread_register
和caml_c_thread_unregister
函数已重新导入到 systhreads。在多核 OCaml 中,由 C 代码创建的线程将被注册到域 0 线程链接。
域本地存储
-
ocaml-multicore/ocaml-multicore#404 Domain.DLS.new_key 接受一个初始化器
Domain.DLS.new_key
现在接受一个初始化器参数,以便为一个键分配一个关联的值,如果该键尚未初始化。此外,Domain.DLS.get
现在不再返回一个可选值。 -
ocaml-multicore/ocaml-multicore#405 重新设计 Domain.DLS.get 搜索函数,使其不再分配内存
Domain.DLS.get
已更新,以消除任何内存分配,如果键已存在于域本地存储中。该 PR 还将search
函数更改为接受所有输入作为变量,而不是环境中的闭包。
Lwt
-
ocaml-multicore/multicore-opam#33 添加 lwt.5.3.0+multicore
Lwt.5.3.0 并发库已添加,以支持多核 OCaml 的 CPU 并行。Sudha Parimala 撰写了一篇介绍其安装和使用的 博文。
-
使用最近的 Lwt 构建的 基于异步效果的 IO,以及 HTTP 效果演示已更新以使用多核 OCaml、Lwt 和 httpaf。演示源代码可在 http-effects 存储库中找到。
杂项
-
ocaml-multicore/ocaml-multicore#406 删除 RPC 对 ephemeron 的使用
使用停止世界次要 GC 不需要域间机制,因此在 ephemeron 实现中已删除了相同的机制。该 PR 还清理并简化了 ephemeron 数据结构和代码。
-
ocaml-multicore/ocaml-multicore#411 修复
internal_variable_names
中的 presume 和 presume_arg 的拼写错误修复了一个次要拼写错误,在
internal_variables_names.ml
中将Presume
和Presume_arg
重命名。 -
ocaml-multicore/ocaml-multicore#414 修复
Ppoll
semantics_of_primitives
条目Ppoll
的semantics_of_primitives
条目已修复,该条目会导致 flambda 构建删除轮询点。 -
ocaml-multicore/ocaml-multicore#416 修复回调效果错误
该 PR 修复了 C 到 OCaml 回调阻止效果跨越 C 回调边界的错误。堆栈父级在回调之前清除,并在之后恢复。它还使堆栈父级成为一个本地根,以便 GC 可以从回调中看到它。
基准测试
正在进行
配置
-
ocaml-bench/ocaml-bench-scripts#12 添加对并行 multibench 目标和 JSON 输入的支持
RUN_CONFIG_JSON
和BUILD_BENCH_TARGET
变量现在已添加,并在运行时传递以执行并行基准测试。指定了默认值,以便串行基准测试仍然可以在没有明确要求的情况下运行。 -
ocaml-bench/sandmark#180 笔记本重构和用户更改
正在进行重构工作,以使并行基准测试变得互动。The Littlest JupyterHub 安装上的用户帐户可以直接访问系统上从
ocaml-bench-scripts
生成的基准测试结果。 -
ocaml-bench/sandmark#189 添加 JSON 配置文件中包装器的环境支持
OCAMLRUNPARAM 现在作为环境变量传递给运行时基准测试,因此可以使用不同的参数值获得多个结果进行比较。用例和讨论可在 使用不同的 OCAMLRUNPARAM 运行基准测试 问题中找到。环境变量可以在
run_config.json
文件中指定,如下所示{ "name": "orun_2M", "environment": "OCAMLRUNPARAM='s=2M'", "command": "orun -o %{output} -- taskset --cpu-list 5 %{command}" }
提议
-
ocaml-bench/sandmark#159 实现一种更好的方法来描述 tasklet cpulist
正在讨论实现一种更好的方法来获取基准测试运行的 taskset 核心列表。这是为了能够指定超线程核心、NUMA 区域以及要用于并行基准测试的特定核心。
-
ocaml-bench/sandmark#179 [RFC] 基于运行时间对基准测试进行分类
提供了一个基于基准测试运行时间对其进行分类的建议。建议以下分类类型
lt_1s
:运行时间少于 1 秒的基准测试。lt_10s
:运行时间至少 1 秒,但少于 10 秒的基准测试。10s_100s
:运行时间至少 10 秒,但少于 100 秒的基准测试。gt_100s
:运行时间至少 100 秒的基准测试。
有关此 PR 的更多信息,请访问 基准测试分类。
-
我们正在探索使用
opam-compiler
切换环境来构建 Sandmark 基准测试套件。合并了 systhreads 兼容性支持 后,我们现在可以在切换环境中本地安装 dune,以及其他基准测试。通过这种方法,我们希望将我们的基准测试套件模块化,并最终完全使用 OCaml 工具和生态系统。
杂项
-
ocaml-bench/sandmark#181 无锁映射基准测试
这是一个基于 Prokopec,A. 等人 (2011) 的无锁并发哈希数组映射 Trie 的实现。该缓存感知实现基准测试目前正在审核中。
-
ocaml-bench/sandmark#183 将数值分析基准测试命名为 crout_decomposition
Sandmark 库中存在几个 LU 分解基准测试,此 PR 将
numerical-analysis/lu_decomposition.ml
基准测试重命名为crout_decomposition.ml
。这样做是为了解决 重命名数值分析中的 lu_decomposition 基准测试,因为这两个基准测试的实现不同,容易造成命名混淆。
已完成
-
ocaml-bench/sandmark#177 在归一化图中显示原始基线数据
现在,原始基线数据已包含在顺序笔记本输出的归一化图中。例如,
maxrsskb
的图形如下所示。
-
ocaml-bench/sandmark#178 更改为使用 Initializer 的新 Domain.DLS API
multicore-minilight
和multicore-numerical
基准测试现已更新,使用带有 Initializer 的新 Domain.DLS API。 -
ocaml-bench/sandmark#185 清理现有的效果基准测试
此 PR 确保代码在没有任何警告的情况下编译,并添加了
multicore_effects_run_config.json
配置文件和run_all_effect.sh
脚本以执行相同的操作。 -
ocaml-bench/sandmark#186 用于覆盖代码路径的非常简单的效果微基准测试
一组四个微基准测试现已添加到 Sandmark 测试套件中,用于测试我们效果系统的吞吐量。这些包括
effect_throughput_clone
、effect_throughput_val
、effect_throughput_perform
和effect_throughput_perform_drop
。 -
ocaml-bench/sandmark#187 为效果实现“递归”基准测试
现在,一组递归基准测试已包含在 Sandmark 中,用于衡量效果的开销。这受到 (Manticore 基准测试)[https://github.com/ManticoreProject/benchmark/] 的启发。
OCaml
正在进行
-
ocaml/ocaml#9876 不要在处理器寄存器中缓存 young_limit
此 PR 删除了 ARM64、PowerPC 和 RISC-V 端口中在寄存器中缓存
young_limit
的操作。Sandmark 基准测试目前正在相应的硬件上进行测试。 -
ocaml/ocaml#9934 用于清除的预取优化
对
sweep_slice
进行优化的几个补丁进行了 Sandmark 基准测试,并且还测试了预取的使用。目标是减少 GC 期间的缓存未命中。
已完成
-
ocaml/ocaml#9947 添加裸指针动态检查器
现在在运行时对“裸指针”(危险的堆外指针)进行检查,并且在 PR 中添加了三种模式的测试:裸指针、裸指针和动态检查器,以及没有裸指针。
-
ocaml/ocaml#9951 确保标记堆栈推送优化处理裸指针
此 PR 添加了对是否将对象推入标记堆栈的精确检查,以处理裸指针。
我们感谢社区中所有 OCaml 用户和开发人员对该项目的持续支持、审查和贡献。
缩写
- AEIO:基于异步效果的 IO
- API:应用程序编程接口
- ARM:高级 RISC 机器
- CPU:中央处理器
- DEC:域执行上下文
- DLS:域本地存储
- GC:垃圾收集器
- HTTP:超文本传输协议
- JSON:JavaScript 对象表示法
- NUMA:非一致内存访问
- OPAM:OCaml 包管理器
- OS:操作系统
- PR:拉取请求
- RISC-V:精简指令集计算 - V
- RPC:远程过程调用
- STW:停止世界