2015-11-14 12 views
7

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),

  1. "linspace_vec" (xem danh sách dưới đây) sử dụng Vec
  2. "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); 
    } 
} 
+0

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

Trả lời

14

trong versio thứ hai của bạn n, bạn sử dụng loại Box<&'a mut [T]>, điều đó có nghĩa là có hai cấp độ vô hướng để đạt được một số T, vì cả hai số Box& đều là con trỏ.

Thay vào đó, điều bạn muốn là Box<[T]>. Tôi nghĩ cách duy nhất để xây dựng một giá trị như vậy là từ một số Vec<T>, sử dụng phương thức into_boxed_slice. Lưu ý rằng lợi ích duy nhất là bạn mất trường capacityVec sẽ có. Trừ khi bạn cần phải có rất nhiều các mảng trong bộ nhớ cùng một lúc, chi phí có thể là không đáng kể.

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 
} 
+0

Wow, các bạn nhanh chóng trả lời :) Cảm ơn! – poidl

+1

Có một cách khác để tạo 'Hộp <[T]>', từ một mảng có kích thước cố định đóng hộp ('Hộp <[T; N]>'), nó có thể được đúc hoặc nó sẽ đơn giản ép buộc. – bluss

+0

@bluss: nhưng tôi có thể tạo [T; N] với VARIABLE N (trước khi tôi đóng hộp) không? – poidl

Các vấn đề liên quan