2009-03-06 35 views
5

Tôi có một câu hỏi về std :: vector.Xóa sạch mọi vòng lặp lặp lại. Cách hiệu quả nhất của bộ nhớ là gì?

Tôi có một thuật toán rất chuyên sâu về bộ nhớ mà tôi cho rằng dự đoán kích thước vectơ và đặt đủ bộ nhớ cho các vectơ trước sẽ giúp tôi rất nhiều trong việc giảm mức sử dụng bộ nhớ.

Điều nào sau đây là tốt hơn:

for (...) { 
    std::vector<Type> my_vector; 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

Hoặc này:

std::vector my_vector; 
for (...) { 
    my_vector.clear(); 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

Xin vui lòng cho tôi biết đó là tốt nhất, hoặc nếu có một cách thậm chí tốt hơn để làm công cụ.

Cảm ơn bạn rất nhiều trước!

+0

Đây không phải là câu hỏi loại ý kiến. Bạn nên đo sự khác biệt cho hệ thống cụ thể của bạn. –

Trả lời

11

Với biến thể đầu tiên bạn phân bổ lại bộ đệm của vectơ trên mỗi lần lặp - điều này thường khá tốn kém. Với biến thể thứ hai, bạn chỉ thỉnh thoảng phân bổ lại. Biến thể thứ hai tốt hơn vì tốc độ là ưu tiên của bạn.

Không rõ bạn hỏi câu hỏi về số lượng phần tử được biết đến từ đâu. Có lẽ bạn thậm chí có thể nhanh chóng tính toán số lượng tối đa của các phần tử cho tất cả các lần lặp lại, thiết lập này là kích thước bộ đệm và không có sự phân bổ lại.

+0

thường khá tốn kém: Đó là một tuyên bố táo bạo mà không cần lược tả. Bộ cấp phát bộ nhớ C++ được thiết kế cho chính xác loại tình huống này, vì vậy tôi nghi ngờ nó (nhưng ngay cả xác nhận đó là in đậm và cần được kiểm tra). –

+0

Vâng, chúng tôi đã từng có hồ sơ trong một tình huống tương tự. Sự tái phân bổ như vậy trong các trường hợp cực đoan đã chịu trách nhiệm cho khoảng 95% thời gian - một bộ đệm được cấp phát, dữ liệu được sao chép, phân tích ngắn gọn và sau đó bộ đệm bị loại bỏ. Điều đó khá đáng ngạc nhiên. – sharptooth

+0

Điều này dẫn đến kết luận rằng nếu một người muốn thực hiện nhanh chóng, anh ta nên tránh những sự phân bổ không cần thiết. – sharptooth

5

Cách thứ hai có thể nhanh hơn một chút, nhưng tôi tìm thấy trình dọn dẹp đầu tiên.

+0

Làm sạch là ok, nhưng trong tình hình của tôi, làm sạch không quan trọng như thuật toán của tôi cần tối ưu hóa càng nhiều càng tốt. Các bài kiểm tra không được tối ưu hóa của tôi có thể sử dụng bộ nhớ 10GB không có vấn đề gì. – Nailer

+0

Sau đó, bạn không nên đặt câu hỏi như thế này (ý kiến ​​của mọi người có thể rất/sai). Những gì bạn nên làm là cấu hình mã và đặt nó trên một tập dữ liệu nhỏ hơn. –

5

Vì sự khác biệt trong mã là tầm thường, tại sao không kiểm tra cả hai cách tiếp cận và xem phương thức nào phù hợp nhất với ứng dụng cụ thể của bạn?

1

Nó phụ thuộc một chút vào cách Loại cần được xây dựng/hủy bỏ, tôi sẽ nói. Nếu nó là một POD mà không yêu cầu hủy diệt, bạn có thể bỏ qua rõ ràng(), trong đó kêu gọi tất cả các hàm hủy trong một vòng lặp, và sử dụng nó như một mảng tĩnh thay vì:

std::vector<Type> my_vector(size); 
for (...) 
{ 
    int index = 0; 
    // Do stuff 
    my_vector[index] = some_value; 
} 

(Nên biết trước: Mã chưa được kiểm tra)

+0

Nếu nó là một POD, tôi mong đợi các vector để tối ưu hóa sự hủy diệt đi trong mọi trường hợp. Kiểm tra trước khi nhảy đến kết luận về hiệu suất – jalf

+0

Đồng ý. (với Jalf) –

+0

Về lý thuyết, bạn nói đúng, jalf. Lấy câu trả lời của tôi như là một gợi ý rằng bạn có thể phá hủy mọi thứ rất nhiều, và có lẽ một số công việc có thể được thực hiện ở đó. –

1

... đặt đủ bộ nhớ cho vectơ trước sẽ giúp tôi rất nhiều với giảm sử dụng bộ nhớ

err ... những gì ?! Điều đó làm cho không có ý nghĩa gì cả. Bộ nhớ dự trữ không giúp giảm mức sử dụng bộ nhớ theo bất kỳ cách nào. Nó ngăn chặn sự cần thiết phải tái phân bổ liên tục mà làm cho mọi thứ nhanh hơn, nhưng theo như sử dụng đi bạn sẽ không nhận được lợi ích.

+0

Thật vậy, số lượng byte miễn phí sẽ bằng nhau, nhưng đoạn lớn nhất có thể phân bổ sẽ nhỏ hơn: phân bổ lại nhiều lần cho đến khi bạn nhận được kích thước phù hợp cuối cùng sẽ phân đoạn đống của bạn. Đến cuối cùng. – xtofl

+0

Trên hết, các vec-tơ phải có bộ nhớ liên tục, vì vậy nếu vectơ hiện tại không thể được mở rộng nữa, toàn bộ khối mới cần phải được cấp phát, vector cũ được sao chép và deallocated. Bộ nhớ tạm thời sử dụng (oldsize + newsize). Nếu bạn có yêu cầu bộ nhớ rất lớn, điều này trở nên có liên quan. – Pieter

+0

Vectơ phân bổ gấp đôi bộ nhớ mà chúng cần khi bạn gọi hàm chắp thêm và không có đủ chỗ cho phần tử tiếp theo. Điều này có nghĩa rằng nếu tôi có một vectơ đủ lớn cho 100 phần tử, khi tôi thêm phần tử 101, vectơ sẽ cấp phát bộ nhớ đủ cho 200 phần tử. – Nailer

6

Tôi cho rằng dự đoán kích thước véc-tơ và đặt đủ bộ nhớ cho các véc tơ trước sẽ giúp ích rất nhiều cho việc giảm mức sử dụng bộ nhớ.

Hãy thử và hành động như một kỹ sư không phải là thầy bói. Tạo một thử nghiệm và đo lường sự khác biệt.

0

Nếu bạn cần thực hiện rất nhiều phụ thêm, hãy sử dụng std :: deque thay vì std :: vector và chỉ sử dụng "push_back".

0

thì sao?

std::vector<DataType> my_vector; 
my_vector.resize(sizeof(yourData)); 
memcpy(reinterpret_cast<char*>(&my_vector), &yourData, sizeof(yourData)); 
+0

Tại sao không std :: copy()? –

1

Thứ hai sẽ sử dụng bộ nhớ tối đa của tất cả việc sử dụng thông qua vòng lặp, tức là kích thước tối đa của các loại stuff_count. std::vector::clear() does not necessarily free memory. Ví dụ: nếu bạn gọi std::vector::capacity() trước và sau std::vector::clear(), việc triển khai tuân thủ tiêu chuẩn có thể trả về cùng một giá trị.

Tốt nhất, bạn sẽ giảm số lần bạn cấp phát bộ nhớ với lược đồ trên. Nhưng bạn chắc chắn sẽ không giảm được dấu chân bộ nhớ tại bất kỳ thời điểm nào. Nếu bạn muốn thu nhỏ số lượng bộ nhớ đã dành riêng, bạn nên sử dụng thành ngữ hoán đổi véc tơ:

std::vector<type>().swap(my_vector); 
my_vector.reserve(stuff_count); 

Hoặc giải pháp đầu tiên của bạn, vì hiệu ứng tổng thể sẽ giống nhau.

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