1. Học hỏi
  2. /
  3. Khoa Học
  4. /
  5. Tối ưu hóa mã R với Rcpp

Connected

Bài tập

Đừng thay đổi kích thước của vector Rcpp

Các lớp vector của Rcpp được thiết kế như những lớp bao rất mỏng quanh các vector của R. Điều này kéo theo hệ quả về hiệu năng: việc tăng hoặc giảm kích thước của chúng đồng nghĩa với việc tạo một vector mới có kích thước đúng và sao chép dữ liệu liên quan. Đây là thao tác rất chậm, nên cần tránh.

Nếu có thể, bạn nên cấu trúc mã để trước tiên tính kích thước cuối cùng của vector, rồi cấp phát nó với đúng kích thước đó.

Hãy xem một ví dụ chọn các giá trị dương từ một vector, tương đương với x[x > 0] trong R. Vì bạn không biết trước sẽ có bao nhiêu số dương, rất dễ bị cám dỗ bắt đầu với một vector độ dài 0 và nối thêm một giá trị mỗi khi tìm thấy. Ở đây, push_back() là hàm dùng để nối thêm một giá trị.

NumericVector bad_select_positive_values_cpp(NumericVector x) {
  NumericVector positive_x(0);
  for(int i = 0; i < x.size(); i++) {
    if(x[i] > 0) {
      positive_x.push_back(x[i]);
    }
  }
  return positive_x;
}

Đáng tiếc, hàm này sẽ chậm vì nó phải liên tục tạo vector mới và sao chép dữ liệu. Xem bạn có thể làm tốt hơn không!

Hướng dẫn

100 XP
  • Hoàn thiện định nghĩa một hàm hiệu quả hơn, good_select_positive_values_cpp() để chọn các số dương.
    • Ở vòng lặp for đầu tiên, nếu phần tử thứ i của x lớn hơn 0, cộng thêm một vào n_positive_elements.
    • Sau vòng lặp đó, cấp phát một vector số, positive_x, có kích thước n_positive_elements.
    • Ở vòng lặp for thứ hai, tiếp tục kiểm tra xem phần tử thứ i của x có lớn hơn 0 không.
    • Khi điều kiện đúng, gán phần tử thứ j của positive_x bằng phần tử thứ i của x, rồi cộng thêm một vào j.
  • bad_select_positive_values_cpp() đã có sẵn trong không gian làm việc của bạn để so sánh. Xem đầu ra của console để thấy sự khác biệt thời gian chạy khi benchmark.