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 不包含 endmark_stack_push 更接近于主干,并且 caml_shrink_mark_stack 已从主干中移植。

  • ocaml-multicore/ocaml-multicore#429 修复 STW 中断竞争

    该 PR 中修复了 caml_try_run_on_all_domains_with_spin_work 中的 STW 中断竞争,其中 stw_requestenter_spin_callbackenter_spin_data 字段在中断其他域后进行初始化。

已完成

Systhreads 支持

  • ocaml-multicore/ocaml-multicore#381 使用 pthreads 重新实现 Systhreads(域执行上下文)

    使用 pthreads 重新实现 Systhreads 已完成用于多核 OCaml。引入了域执行上下文 (DEC),它允许多个线程在域之上运行。

  • ocaml-multicore/ocaml-multicore#410 systhreads:caml_c_thread_registercaml_c_thread_unregister

    caml_c_thread_registercaml_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 中将 PresumePresume_arg 重命名。

  • ocaml-multicore/ocaml-multicore#414 修复 Ppoll semantics_of_primitives 条目

    Ppollsemantics_of_primitives 条目已修复,该条目会导致 flambda 构建删除轮询点。

  • ocaml-multicore/ocaml-multicore#416 修复回调效果错误

    该 PR 修复了 C 到 OCaml 回调阻止效果跨越 C 回调边界的错误。堆栈父级在回调之前清除,并在之后恢复。它还使堆栈父级成为一个本地根,以便 GC 可以从回调中看到它。

基准测试

正在进行

配置

  • ocaml-bench/ocaml-bench-scripts#12 添加对并行 multibench 目标和 JSON 输入的支持

    RUN_CONFIG_JSONBUILD_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 的图形如下所示。

PR 177 Image |690x258

  • ocaml-bench/sandmark#178 更改为使用 Initializer 的新 Domain.DLS API

    multicore-minilightmulticore-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_cloneeffect_throughput_valeffect_throughput_performeffect_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:停止世界