我想要一个功能
Drop
,所以我不必担心释放内存显而易见的选择是Vec
,但它与堆上的盒装切片相比如何?Vec
更强大,但我需要数组数学,在我的情况下,不需要像push/pop这样的东西.我们的想法是拥有功能较少但速度更快的东西.
下面我有两个版本的"linspace"函数(la Matlab和numpy),
Vec
两者都用得像
let y = linspace_*(start, stop, len);
Run Code Online (Sandbox Code Playgroud)
其中y
是长度为线性间隔的"阵列"(即Vec
(1)中的(1)和(2)中的盒装切片)len
.
对于长度为1000的小"阵列",(1)更快.对于长度为4*10 ^ 6的大型阵列,(1)为SLOWER.这是为什么?我在(2)做错了吗?
当参数len
= 1000时,仅通过调用函数进行基准测试就会产生
(1) ... bench: 879 ns/iter (+/- 12)
(2) ... bench: 1,295 ns/iter (+/- 38)
当参数len
= 4000000时,基准测试结果为
(1) ... bench: 5,802,836 ns/iter (+/- 90,209)
(2) ... bench: 4,767,234 ns/iter (+/- 121,596)
(1)的清单:
pub fn linspace_vec<'a, T: 'a>(start: T, stop: T, len: usize) -> Vec<T>
where
T: Float,
{
// get 0, 1 and the increment dx as T
let (one, zero, dx) = get_values_as_type_t::<T>(start, stop, len);
let mut v = vec![zero; len];
let mut c = zero;
let ptr: *mut T = v.as_mut_ptr();
unsafe {
for ii in 0..len {
let x = ptr.offset((ii as isize));
*x = start + c * dx;
c = c + one;
}
}
return v;
}
Run Code Online (Sandbox Code Playgroud)
(2)的清单:
pub fn linspace_boxed_slice<'a, T: 'a>(start: T, stop: T, len: usize) -> Box<&'a mut [T]>
where
T: Float,
{
let (one, zero, dx) = get_values_as_type_t::<T>(start, stop, len);
let size = len * mem::size_of::<T>();
unsafe {
let ptr = heap::allocate(size, align_of::<T>()) as *mut T;
let mut c = zero;
for ii in 0..len {
let x = ptr.offset((ii as isize));
*x = start + c * dx;
c = c + one;
}
// IS THIS WHAT MAKES IT SLOW?:
let sl = slice::from_raw_parts_mut(ptr, len);
return Box::new(sl);
}
}
Run Code Online (Sandbox Code Playgroud)
Fra*_*gné 21
在你的第二个版本,您使用的类型Box<&'a mut [T]>
,这意味着有两个层次间接达成T
,因为这两个Box
和&
的指针.
你想要的是一个Box<[T]>
.我认为构建这样一个值的唯一合理方法是Vec<T>
使用该into_boxed_slice
方法.请注意,唯一的好处是你会失去capacity
一个Vec
可能拥有的领域.除非您需要在内存中同时拥有大量这些数组,否则开销可能无关紧要.
pub fn linspace_vec<'a, T: 'a>(start: T, stop: T, len: usize) -> Box<[T]>
where
T: Float,
{
// get 0, 1 and the increment dx as T
let (one, zero, dx) = get_values_as_type_t::<T>(start, stop, len);
let mut v = vec![zero; len].into_boxed_slice();
let mut c = zero;
let ptr: *mut T = v.as_mut_ptr();
unsafe {
for ii in 0..len {
let x = ptr.offset((ii as isize));
*x = start + c * dx;
c = c + one;
}
}
v
}
Run Code Online (Sandbox Code Playgroud)