是否可以对非重叠内存进行安全的可变别名?

时间:2015-10-21 01:36:26

标签: rust

我正在寻找一种方法来获取一个大对象并将其分解为较小的可变子对象,这些对象可以并行处理。

类似的东西:

struct PixelBuffer { data:Vec<u32>, width:u32, height:u32 }
struct PixelBlock { data:Vec<u32> }
impl PixelBuffer {
  fn decompose(&'a mut self) -> Vec<Guard<'a, PixelBlock>>> {
    ...
  }
}

可以并行处理生成的PixelBlock,并且父{4}}将保持锁定状态,直到删除所有PixelBuffer为止。

这实际上是可变的指针别名; Guard<PixelBlock>中的大数据块将通过每个PixelBuffer直接修改。

但是,每个PixelBlock都与PixelBlock中的内部数据不重叠。

你当然可以在不安全的代码中执行此操作(内部缓冲区是一个原始指针;为每个PixelBuffer生成一个新的外部指针);但是可以使用安全代码实现相同的结果吗?

(注意:我愿意使用从libc :: malloc分配的数据块,如果这有帮助吗?)

2 个答案:

答案 0 :(得分:3)

这很好,并且是例如迭代器如何工作的自然结果:next方法分发了一系列与其来自的引用无关的值,即{{1} }。这自动意味着产生fn next(&mut self) -> Option<Self::Item>指针的任何迭代器(如&mut)都会产生指向非重叠内存的指针,因为其他任何东西都是不正确的。

并行使用此功能的一种方法就像我的slice.iter_mut()库,例如Pool::for_

(您需要提供有关simple_parallel内部的更多详细信息,以便更具体地说明在这种情况下如何执行此操作。)

答案 1 :(得分:3)

没有办法完全避免不安全的Rust,因为编译器目前无法评估子片的安全性。但是,标准库包含提供可以使用的安全包装的代码。

阅读std::slice::Chunksstd::slice::ChunksMut

示例代码:https://play.rust-lang.org/?gist=ceec5be3e1530c0a6d3b&version=stable

但是,您的下一个问题是将切片发送到单独的线程,因为最好的方法是thread::scoped,由于今年发现的一些安全问题,目前已将其弃用...

另外,请记住Vec<_>拥有其内容,而切片只是一个视图。通常,您希望以切片的形式编写大多数函数,并且只保留一个“Vec”来保存数据。