Tôi đang cố gắng học Rust và tôi dần dần bắt đầu nhận ra nó thú vị đến mức nào. Tôi muốn có một chức năng đểSo sánh hiệu suất của một Vec và một miếng cắt đóng hộp
- phân bổ một chiều dài thay đổi cơ bản "mảng" (theo nghĩa chung của từ, không nhất thiết phải là loại Rust) phao trên heap
- khởi tạo nó với các giá trị
- thực hiện thả, vì vậy tôi không phải lo lắng về việc giải phóng bộ nhớ và thứ gì đó để lập chỉ mục hoặc lặp lại.
Lựa chọn hiển nhiên là Vec
, nhưng nó so sánh như thế nào với một lát đóng hộp trên heap? Vec
là mạnh hơn, nhưng tôi cần mảng cho toán số và, trong trường hợp của tôi, không cần những thứ như push/pop. Ý tưởng là để có một cái gì đó với ít tính năng hơn, nhưng nhanh hơn.
Dưới đây tôi có hai phiên bản của một hàm "linspace" (a la Matlab và NumPy),
- "linspace_vec" (xem danh sách dưới đây) sử dụng
Vec
- "linspace_boxed_slice" (xem danh sách dưới đây) sử dụng một lát đóng hộp
Cả hai đều được sử dụng như
let y = linspace_*(start, stop, len);
trong đó y là một mảng "khoảng cách" tuyến tính (tức là một Vec trong (1) và một lát cắt trong (2)) của chiều dài len.
Bây giờ câu hỏi: Đối với các "mảng nhỏ" có chiều dài 1000, (1) là nhanh hơn. Đối với mảng lớn có chiều dài 4 * 10^6, (1) là SLOWER. Tại sao vậy? Tôi có làm gì sai trong (2) không?
Khi đối số len
= 1000, điểm chuẩn bằng cách chỉ cần gọi kết quả chức năng trong
- (1) ... băng ghế dự bị: 879 ns/iter (+/- 12)
- (2) ... băng ghế dự bị: 1.295 ns/iter (+/- 38)
Khi đối số len
= 4000000, kết quả điểm chuẩn trong
- (1) ... băng ghế dự bị: 5.802.836 ns/iter (+/- 90.209)
- (2) ... băng ghế dự bị: 4.767.234 ns/iter (+/- 121.596)
Danh bạ (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
}
danh bạ nhà (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);
}
}
Nếu tôi hiểu chức năng, đừng nghĩ rằng bạn cần phải giảm xuống mức đó để đi nhanh. Iterator khá tuyệt vời: [bench: 2,755,606 ns/iter (+/- 408,352)] (http://is.gd/ePFynw). – Shepmaster