我正在寻找分配小型结构的向量。
这需要30毫秒并线性增加:
let v = vec![[0, 0, 0, 0]; 1024 * 1024];
这需要数十微秒:
let v = vec![0; 1024 * 1024];
是否有更有效的解决方案?我可以接受不安全的代码。
Fang Zhang's answer在通常情况下是正确的。您询问的代码有点特殊:它可以使用alloc_zeroed
,但不是。正如Stargateur在问题评论中所指出的那样,随着将来语言和库的改进,两种情况都有可能利用这种加速。
这通常应该不是问题。一次初始化整个大向量可能不是您经常执行的操作。大分配通常是长期存在的,因此您不会在紧密的循环中创建和释放它们-初始化向量的成本很少会支付。除了求助于unsafe
之外,我还要看一下我的算法并尝试理解为什么单个memset
会造成如此大的麻烦。
但是,if您偶然知道all-bits-zero是一个可接受的初始值,并且if您绝对不能容忍这种减速,您可以通过以下方式对标准库进行最终运行:调用alloc_zeroed
并使用Vec
创建from_raw_parts
。 Vec::from_raw_parts
为unsafe
,因此必须绝对确定分配的内存的大小和对齐方式正确。将来,使用现在不稳定的Layout::array
构造函数,这会稍微容易一些,但是现在您只需要自己计算大小和对齐即可。这是一个例子:
Layout::array
pub fn make_vec() -> Vec<[i8; 4]> {
// Unstable: std::alloc::Layout::array::<[i8; 4]>(1_000_000).unwrap()
let layout = std::alloc::Layout::from_size_align(4_000_000, 1).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,
)
}
}
How to perform efficient vector initialization in Rust?是特例。如果将其更改为vec![0; 1024 * 1024]
,将会看到性能急剧下降。
通常,对于非零元素vec![1; 1024 * 1024]
,e
将clone元素vec![e; n]
倍,这是主要成本。对于等于n
的元素,还有其他系统方法可以初始化内存,这要快得多。
所以您的问题的答案为否。