我想要一个函数
- 在堆上分配浮点数的基本可变长度"数组"(一般意义上,不一定是 rust 类型)
- 用值初始化它
- 实现
Drop
,所以我不必担心释放内存 - 实现一些用于索引或迭代的东西
显而易见的 Select 是Vec
,但它与堆上的盒装切片相比如何?Vec
更强大,但我需要用于数值计算的数组,在我的情况下,不需要push/pop之类的东西.这样做的目的是让功能更少,但速度更快.
下面我有两个版本的"linspace"函数(la Matlab和numpy),
- "linspace_vec"(见下表)使用
Vec
- "linspace_boxed_slice"(见下面的 list )使用一个boxed slice
两者都像
let y = linspace_*(start, stop, len);
其中,y
是长度为len
的线性间隔"数组"(即(1)中的Vec
和(2)中的盒式切片).
对于长度为1000的小型"数组",则(1)更快.对于长度为4*10^6的大型数组,(1)较慢.为什么?我在第(2)项中做错了什么吗?
当参数len
=len
0时,仅通过调用函数进行基准测试会导致
(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)
Listing of (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;
}
Listing of (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);
}
}