【问题标题】:Why doesn't Rayon require Arc<_>?为什么 Rayon 不需要 Arc<_>?
【发布时间】:2020-04-14 09:29:32
【问题描述】:

Programming Rust 的第 465 页上,您可以找到代码和解释(重点由我添加)

use std::sync::Arc;

fn process_files_in_parallel(filenames: Vec<String>,
                             glossary: Arc<GigabyteMap>)
    -> io::Result<()>
{
    ...
    for worklist in worklists {
        // This call to .clone() only clones the Arc and bumps the
        // reference count. It does not clone the GigabyteMap.
        let glossary_for_child = glossary.clone();
        thread_handles.push(
            spawn(move || process_files(worklist, &glossary_for_child))
        );
    }
    ...
}

我们更改了词汇表的类型:要并行运行分析,调用者必须通过 Arc::new(giga_map) 传入一个 Arc&lt;GigabyteMap&gt;,这是一个指向已移动到堆中的 GigabyteMap 的智能指针。当我们调用glossary.clone() 时,我们正在复制Arc 智能指针,而不是整个GigabyteMap。这相当于增加引用计数。通过此更改,程序可以编译并运行,因为它不再依赖于引用生命周期。 只要任何线程拥有Arc&lt;GigabyteMap&gt;,它就会使地图保持活动状态,即使父线程提前退出。不会有任何数据竞争,因为 Arc 中的数据是不可变的。

在下一节中,他们展示了用 Rayon 重写的内容,

extern crate rayon;

use rayon::prelude::*;

fn process_files_in_parallel(filenames: Vec<String>, glossary: &GigabyteMap)
    -> io::Result<()>
{
    filenames.par_iter()
        .map(|filename| process_file(filename, glossary))
        .reduce_with(|r1, r2| {
            if r1.is_err() { r1 } else { r2 }
        })
        .unwrap_or(Ok(()))
}

您可以在重写为使用 Rayon 的部分中看到它接受 &amp;GigabyteMap 而不是 Arc&lt;GigabyteMap&gt;。他们没有解释这是如何工作的。为什么 Rayon 不需要 Arc&lt;GigabyteMap&gt;? Rayon 如何不接受直接推荐?

【问题讨论】:

标签: rust reference-counting lifetime-scoping


【解决方案1】:

Rayon 可以保证迭代器不会超过当前堆栈帧,这与我在第一个代码示例中假设的 thread::spawn 不同。具体来说,par_iter 在底层使用了类似 Rayon 的 scope 函数,它允许生成一个“附加”到堆栈并在堆栈结束之前加入的工作单元。

因为 Rayon 可以保证(通过生命周期,从用户的角度来看)任务/线程在函数调用 par_iter 退出之前加入,它可以提供比标准库的 @987654327 更符合人体工程学的 API @。

Rayon 在 scope function's documentation 中对此进行了扩展。

【讨论】:

  • 当核心 Rust 做不到时,人造丝如何做出这种保证? Rayon 在内部使用 Arc 吗?
  • std 可以做这个保证,但目前没有这样的功能(留给像 rayon 和 crossbeam 这样的库)。 Rayon 保证线程在 scope 函数退出之前加入(无论是由于 unwinding 还是正常返回);因为mem::forget,这不能在返回类型中使用基于 RAII 的 API 来完成。
猜你喜欢
  • 2021-02-23
  • 1970-01-01
  • 2019-10-27
  • 2020-05-03
  • 2018-03-18
  • 1970-01-01
  • 2015-07-28
  • 2018-07-30
相关资源
最近更新 更多