2016-07-20 18 views
6

Tôi đang sử dụng std::deque. Tôi chắc chắn rằng thay thế một vòng lặp với một push_back với một insert duy nhất sẽ mang lại sự gia tăng hiệu suất. Nó cũng được đề nghị, ví dụ here.Push_back nhanh hơn chèn?

Nhưng giờ tôi không còn chắc chắn nữa.

Tôi đã chạy một số điểm chuẩn trên mã thử nghiệm.

main.cpp:

#include"queueInsert.h" 

#include<Windows.h> 

std::deque<int> queue; 

constexpr size_t len = 64; 

int arr[len]; 

int main() 
{ 
    DWORD startTime = GetTickCount(); 
    for (int i = 0; i < 100000; ++i) 
    { 
     insert(queue, arr, len); 
    } 
    DWORD endTime = GetTickCount(); 

    return endTime - startTime; 
} 

queueInsert.h:

#include<deque> 

void insert(std::deque<int>&, int* arr, int n); 

queueInsert.cpp -push phiên bản

#include "queueInsert.h" 

void insert(std::deque<int>& queue, int* arr, int n) 
{ 
    for (int i = 0; i < n; ++i) 
    { 
     queue.push_back(arr[i]); 
    } 
} 

queueInsert.cpp -insert phiên bản

#include "queueInsert.h" 

void insert(std::deque<int>& queue, int* arr, int n) 
{ 
    queue.insert(queue.end(), arr, arr + n); 
} 

Tôi nhận được 203 mili giây với push_back, nhưng 218 với insert.

Thay đổi len-6, và tăng lặp để mốt triệu, giữ cho kết quả tương tự: 219 nhà máy cho push266 cho insert.

Chỉ với len = 640 không push bị thua thiệt, và thậm chí sau đó bởi rất ít: 1531 cho push chống 1437 cho insert.

Tôi đang biên soạn trong phiên bản lần trong VisualStudio 2015 trong môi trường Windows 10

tôi chắc chắn rằng trình biên dịch không làm tối ưu hóa như nội tuyến số liên tục lặp đi lặp lại hoặc pha trộn các vòng, như mỗi khi tôi thay đổi chỉ thực hiện queueInsert.cpp được biên dịch lại.

Tôi đang làm sai địa chỉ? Hoặc tôi có nên giữ push_back nếu số lượng các yếu tố được chèn vào không có khả năng lớn không?

+0

* Tôi chắc chắn trình biên dịch không thực hiện tối ưu hóa * - Hãy xem danh sách lắp ráp. – PaulMcKenzie

+1

Tôi đọc bài báo gốc, không bao giờ là – Slava

+0

Tôi ngụ ý vectơ là chuỗi các phần tử chứ không phải 'std :: vector'. Tôi đã sửa chữa để làm cho ý nghĩa rõ ràng hơn. –

Trả lời

11

deque::insert hiệu quả có 3 cách hoạt động có thể có: chèn chung, chèn ở phía trước, chèn vào phía sau. Do đó, mỗi khi bạn gọi insert, nó phải thực hiện một thử nghiệm để xem cần phải chèn cách nào. Vì vậy, nó có để kiểm tra iterator bạn vượt qua chống lại phía trước và phía sau.

deque::push_back chỉ có 1 chế độ hoạt động: chèn ngược lại.

Lợi thế của việc sử dụng thao tác chèn hàng loạt là vùng chứa có thể phát hiện chính xác lượng bộ nhớ cần phân bổ để thực hiện chèn toàn bộ vì nó có thể nhận được độ dài của vùng lặp. Vì vậy, số lượng lớn chèn lớn hơn, thì càng tốt insert.

Vâng, tốt hơn cho vector ít nhất.

Xem với vector, nếu bạn chèn 30.000 phần tử một lần, bạn có khả năng thực hiện phân bổ lại ~ 14-15 lần. Điều đó có nghĩa là phân bổ bộ nhớ mới và sao chép dữ liệu cũ vào bộ nhớ đó. Trong khi nếu bạn chèn 30.000 phần tử cùng một lúc, bạn sẽ nhận được đơn lẻ phân bổ lại.

deque thường được triển khai dưới dạng một mảng khối có kích thước cố định. Do đó, nếu bạn chèn 30.000 phần tử cùng một lúc, bạn sẽ nhận được ~ 3.000 phân bổ (tùy thuộc vào kích thước khối). Nếu bạn chèn 30.000 phần tử cùng một lúc, bạn sẽ nhận được ... ~ 3.000 phân bổ. Vì vậy, bạn không thực sự tiết kiệm nhiều.

Vì chèn số lượng lớn không khác nhiều so với chèn đơn cho deque, điều xảy ra là cuộc chiến giữa các vấn đề tối ưu hóa vi mô. Mọi cuộc gọi insert đều phải thực hiện so sánh vòng lặp để xem cách thực hiện thao tác chèn đó. Như vậy, các chèn nhỏ hơn, hiệu quả kém hơn insert sẽ được. push_back không có phí trên, nhưng nó là một cuộc gọi hàm cho mỗi phần tử. Vì vậy, nó có chi phí đó.

Do đó, insert có thể sẽ thắng khi số lượng phần tử được thêm vào mỗi lần chèn cao.

+0

Tôi nghĩ về nó, nhưng kết luận nó không thể là quan trọng, là một kiểm tra duy nhất trên nhiều như các yếu tố '64'. Tuy nhiên, tôi đồng ý đây là giải thích có khả năng nhất vào lúc này. –

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