Rust in Everything
基于 rayon 1.12.0

slice 与排序

切片是 rayon 最常见的数据源:长度已知、任意位置可切、split_at_mut 在类型上保证两半不重叠。src/slice/ 共 4233 行,一半是切片的并行迭代器(mod.rs、chunks.rs、rchunks.rs、windows.rs、chunk_by.rs),另一半是 1686 行的 sort.rs。

这一部分两页:

  1. slice producer:par_iter / par_iter_mut、par_chunks 家族、par_windows / par_array_windows(1.12.0 新增)、par_chunk_by / par_split 各自的生产者怎么切;candle softmax 的 par_chunks.zip(par_chunks_mut)。
  2. 并行排序:par_sort 是 std 换算法之前的类 TimSort 归并加三处 join,par_sort_unstable 是 pdqsort 加一处 join;E9 实测 10⁷ 个 u64 约 3 倍于 std,2000 个以下根本不进线程池却慢 1.6–3.3 倍。
flowchart LR
  sl["&[T] / &mut [T]"] --> pi["ParallelSlice / ParallelSliceMut"]
  pi --> prod["各种 Producer:split_at 直接切切片"]
  prod --> br["bridge(06 部分)"]
  pi --> srt["par_sort* / par_sort_unstable*"]
  srt --> ms["par_mergesort:par_chunks_mut(2000) + merge_recurse + par_merge"]
  srt --> qs["par_quicksort:pdqsort recurse,两边 > 2000 时 join"]
  ms --> jn["rayon_core::join"]
  qs --> jn
  br --> jn

实验

编号目录内容页面
E9exp-rayon/par-sort/10³–10⁷ 个随机 u64,四种排序在 12 线程和 1 线程池下的耗时;已排序 / 逆序输入;比较发生在调用线程还是 worker 上并行排序

环境和 06 并行迭代器 相同:M2 Max(8 性能核 + 4 能效核),macOS 不能绑核,release 构建,每组 5 次取中位数,测前 1 分钟和 5 分钟负载都低于 3,页面上写出两者。

切片迭代器的切分规则和其他 indexed 迭代器一样,由 bridge 与自适应切分 决定;par_sort 的第一步也借用了它(par_chunks_mut(2000).with_max_len(1))。

💬 关联讨论

发起讨论
加载中...