2015-06-02 13 views
8

Giả sử bạn viết một lớp ma trận với một số hoạt động:Đảm bảo phát hiện Temporary-> Điểm tên

class matrix 
{ 
public: 
    double operator()(size_t i, size_t j) const; 
    ... 
}; 

matrix operator*(const matrix &lhs, const matrix &rhs); 
... 

Nó làm cho tinh thần để trì hoãn việc đánh giá của một số biểu thức ma trận: M0 * m1 * m2 * m3 * m4 (là một loạt bốn cuộc gọi operator*) có thể hưởng lợi từ việc sử dụng dynamic-programming matrix chain multiplication algorithm; rất phổ biến m0 * m1 tvery efficient dgemm implementation, v.v.

Do đó, thanh toán sẽ trì hoãn việc tính toán thực tế cho đến khi cần. Thay đổi này ở trên thành:

class matrix 
{ 
private: 
    /* 
    * Pointer to an abstract base class - either an actual matrix, 
    * or an expression tree. */ 
    std::shared_ptr<matrix_imp> m_imp; 

public: 
    // Forces compaction - 
    double operator()(size_t i, size_t j) const; 
    ... 
}; 

/* Lazy; creates a matrix with an expression tree using the 
* internals of lhs and rhs. */ 
matrix operator*(const matrix &lhs, const matrix &rhs); 
... 

Mỗi ma trận giữ một đối tượng lớp cơ sở có thể từ một ma trận thực đến cây biểu thức phức tạp. Mỗi hoạt động cố gắng tạo thành một ma trận bằng cách sử dụng thay đổi tối thiểu để thực hiện nội bộ. Một số hoạt động không có sự lựa chọn nào khác ngoài việc đánh giá mọi thứ, thu gọn cây biểu thức và thiết lập việc triển khai bên trong thành một ma trận thực tế.


Vấn đề là, trên thực tế, điều này gây ra phí tổn bộ nhớ rất lớn trong các trường hợp rất phổ biến. Hãy nói rằng bạn đọc từ một tập tin một ma trận dài và hẹp x = x p X q, p >> q, cửa hàng x t x trong một biến, và loại bỏ x. Với đánh giá lười biếng, bộ nhớ là pq >> qq. Tải chúng trong một vòng lặp, và đó là một vấn đề nghiêm trọng. (Tất nhiên, sự nén chặt có thể bị ép buộc sau mỗi lần tải bởi mã máy khách gọi operator(), nhưng đòi hỏi điều này mà không có biện minh thuật toán là xấu và dễ bị lỗi.)

Ban đầu, tôi nghĩ rằng ctor di chuyển là một điểm tốt để tự động nén - đó là chính xác những điểm mà một tạm thời trở thành một đối tượng có tên, và nó được đặt tên đối tượng gây ra tiêu thụ bộ nhớ tăng, vì vậy

matrix(matrix &&other); // <- Force compaction only here 

sẽ xuất hiện để giải quyết tất cả mọi thứ, ví dụ như,

auto res = // <- temp becoming named 
    a * // temp 
    b * // temp 
    c + // temp 
    2 * // temp 
    d; 

bu t nó có thể được tính vào? Ví dụ, hãy xem xét

matrix load_xtx(const string &f_name) 
{ 
    matrix x = ... 
    return x.t() * x; 
} 

auto xtx = load_xtx("foo.hdf5"); // (*) 

được trình biên dịch cấm làm trong (*) một cái gì đó tương tự như những gì nó làm với NRVO, cụ thể là chỉ để xây dựng nó ở vị trí? Thậm chí nếu không, trình biên dịch có thể tối ưu hóa mọi thứ trong các trường hợp khác không?

+1

Sẽ không đơn giản hơn khi thực hiện phép tính thực tế khi ma trận được truy cập, không chỉ được lưu trữ? – Quentin

+0

@Quentin có, nhưng nếu tôi hiểu bạn một cách chính xác, điều này là chính xác những gì gây ra chi phí bộ nhớ khổng lồ. Giả sử bạn có một vòng lặp tải hàng nghìn ma trận x, chuyển từng hàng thành x t x - tất cả trước truy cập đầu tiên (hoàn toàn không tạo ra kịch bản) - loại công cụ này được sử dụng để thùng rác hệ thống. –

+0

Ồ, tôi hiểu rồi. Quentin

Trả lời

2

Vì phương pháp "con trỏ nội bộ" không thể cung cấp tất cả sự linh hoạt cần thiết cho đánh giá chậm, giải pháp điển hình được sử dụng bởi thư viện số C++ là xác định các lớp chuyên biệt triển khai cơ chế đánh giá lười biếng. Câu hỏi SO cũ Lazy evaluation in C++ và câu trả lời tốt nhất của nó cho thấy những điều cơ bản về thiết kế như vậy và một số mã mẫu.Mặc dù tôi không phải là một chuyên gia, tôi nghĩ rằng các ví dụ điển hình của kiến ​​trúc này là các thư viện số Eigen (here some details about its implementation) và Blitz ++, phụ thuộc rất nhiều vào các mẫu (tôi không tìm thấy trên tài liệu cập nhật web minh họa nội bộ của nó, nhưng this article). mô tả một số phần của động cơ của nó và cũng cung cấp một cái nhìn tổng quan rộng hơn về kỹ thuật "mẫu biểu hiện").

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