OCaml 多核 - 2020 年 8 月
欢迎阅读 2020 年 8 月的 OCaml 多核报告(由于 8 月份的放缓,延迟了几周)。此更新以及 以前的更新 由 @shakthimaan、@kayceesrk 和我共同整理。
现在有一些关于 OCaml 多核的演讲在网上免费提供
- 在 OCaml 研讨会上,@sadiq 展示了 "如何在 OCaml 多核中并行化您的代码"
- 在 ICFP 上,@kayceesrk 展示了 "将并行性改造到 OCaml 中",该演讲还获得了杰出论文奖。
- 在 ICFP 上,Glenn Mével 展示了 "Cosmo: 用于 OCaml 多核的并发分离逻辑"。
- 在 WebAssembly 社区小组会议上,@kayceesrk 做了一个关于 OCaml 多核中的效果处理程序 的演讲。这与我们长期努力确保 OCaml 具有针对 WebAssembly 的高效编译策略有关。
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 帮助测试了使用
Core
和Async
的代码大小度量实现,并提供了代码审查变更。
非常欢迎您对使用我们的基准测试套件来调整项目做出的类似上述贡献。与之前的更新一样,我们首先介绍 OCaml 多核更新,然后介绍 Sandmark 基准测试项目的增强功能和错误修复。最后列出了上游 OCaml 的正在进行和已完成的任务,供您参考。
OCaml 多核
正在进行
-
ocaml-multicore/ocaml-multicore#381 使用 pthreads 重新实现 systhreads
此 PR 在领域 API 的添加、与备份线程的交互方式的更改和错误修复方面取得了巨大进展。我们现在可以使用此 PR 为 OCaml 多核构建
dune.2.6.1
和utop
,它已经可以进行审查了! -
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-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/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-multicore/ocaml-multicore#391 对指针使用
Word_val
,并使用Patomic_load
修复了正确处理加载指针的
Patomic_load
的错误。 -
ocaml-multicore/ocaml-multicore#392 在叶函数测试中包含 Ipoll
Ipoll
操作现在已作为外部调用添加到asmcomp/amd64/emit.mlp
中。
基准测试
正在进行
-
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-config
和m4
添加到 Ubuntu 依赖项中。
已完成
基准测试
-
ocaml-bench/sandmark#107 添加 Coq 基准测试
来自 程序形式推理 的
fraplib
库已 dunify 并包含在 Sandmark 中,用于 Coq 基准测试。 -
ocaml-bench/sandmark#151 进化算法并行基准测试
进化算法并行基准测试现已添加到 Sandmark 中。
-
ocaml-bench/sandmark#152 LU 分解:并行随机数初始化
LU 分解基准测试的随机数初始化现在具有并行性,使用
Domain.DLS
和Random.State
。 -
ocaml-bench/sandmark#153 添加计算密集型 Coq 基准测试
BasicSyntax
和AbstractInterpretation
Coq 文件执行大量次要 GC 和分配,并已作为基准测试添加到 Sandmark 中。 -
ocaml-bench/sandmark#155 进化算法的顺序版本
顺序版本的算法用于与其各自的并行实现进行比较。Sandmark 中现在包含了
进化算法
的顺序实现。 -
ocaml-bench/sandmark#157 Minilight 多核:移植到 Task API 和 DLS 以用于随机状态
Minilight 基准测试已移植到使用 Task API,并使用 Domain Local Storage 用于随机状态。速度提升如以下插图所示
-
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
指定prefix
和libdir
。 初始讨论可在 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: 拉取请求