如何有效地创建初始化为相同值的大型项目向量?

dan*_*ptr 6 memory vector rust

我正在寻找分配一个小型结构的向量。

这需要 30 毫秒并线性增加:

let v = vec![[0, 0, 0, 0]; 1024 * 1024];
Run Code Online (Sandbox Code Playgroud)

这需要几十微秒:

let v = vec![0; 1024 * 1024];
Run Code Online (Sandbox Code Playgroud)

对于第一种情况是否有更有效的解决方案?我可以接受不安全的代码。

tre*_*tcl 6

就一般情况而言,张方的回答是正确的。您询问的代码有点特殊:它可以使用alloc_zeroed,但它没有。正如 Stargateur 在问题评论中指出的那样,随着未来语言和库的改进,这两种情况都有可能利用这种加速。

这通常应该不是问题。一次初始化整个大向量可能不是您经常做的事情。大的分配通常是长期存在的,因此您不会在紧密的循环中创建和释放它们——初始化向量的成本很少会被支付。在诉诸 之前unsafe,我会检查一下我的算法并尝试理解为什么单个算法memset会造成如此多的麻烦。

但是,如果您碰巧知道全位为零是可接受的初始值,并且alloc_zeroed绝对不能容忍速度下降,则可以通过调用和创建Vecusing来围绕标准库进行最终运行from_raw_partsVec::from_raw_partsunsafe,所以您必须绝对确定分配的内存的大小和对齐方式是正确的。从 Rust 1.44 开始,您可以Layout::array轻松地做到这一点。这是一个例子:

pub fn make_vec() -> Vec<[i8; 4]> {
    let layout = std::alloc::Layout::array::<[i8; 4]>(1_000_000).unwrap();
    // I copied the following unsafe code from Stack Overflow without understanding
    // it. I was advised not to do this, but I didn't listen. It's my fault.
    unsafe {
        Vec::from_raw_parts(
            std::alloc::alloc_zeroed(layout) as *mut _,
            1_000_000,
            1_000_000,
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

也可以看看


Fan*_*ang 4

vec![0; 1024 * 1024]是一个特例。如果将其更改为vec![1; 1024 * 1024],您会发现性能急剧下降。

通常,对于非零元素evec![e; n]克隆元素n次数,这是主要成本。对于等于 的元素0,还有其他系统方法来初始化内存,这种方法要快得多。

所以你的问题的答案是否定的。