2010-02-28 72 views
18

Tôi có một yêu cầu đơn giản, tôi cần bản đồ loại. tuy nhiên tôi cần thời gian truy xuất nhanh nhất về mặt lý thuyết.Sự khác biệt về hiệu suất giữa bản đồ và unordered_map trong C++

tôi đã sử dụng cả bản đồ và đề xuất unordered_map mới từ tr1 tôi thấy rằng ít nhất là khi phân tích cú pháp tệp và tạo bản đồ, bằng cách chèn phần tử vào thời điểm đó.

bản đồ chỉ mất 2 phút trong khi unordered_map mất 5 phút.

Vì tôi sẽ là một phần của mã được thực hiện trên cụm Hadoop và sẽ chứa ~ 100 triệu mục nhập, tôi cần thời gian truy xuất nhỏ nhất có thể.

Cũng có một thông tin hữu ích khác: hiện dữ liệu (khóa) đang được chèn vào là phạm vi số nguyên từ 1,2, ... đến ~ 10 triệu.

Tôi cũng có thể áp đặt người dùng để chỉ định giá trị tối đa và sử dụng thứ tự như trên, điều đó có ảnh hưởng đáng kể đến việc triển khai của tôi không? (I nghe bản đồ dựa trên cây rb và chèn thứ tự tăng dần dẫn đến hiệu suất tốt hơn (hoặc tồi tệ nhất)?)

đây là mã

map<int,int> Label // this is being changed to unordered_map 
fstream LabelFile("Labels.txt"); 


// Creating the map from the Label.txt 
if (LabelFile.is_open()) 
{ 
    while (! LabelFile.eof()) 
    {    
     getline (LabelFile,inputLine); 
     try 
     { 
      curnode=inputLine.substr(0,inputLine.find_first_of("\t")); 
      nodelabel=inputLine.substr(inputLine.find_first_of("\t")+1,inputLine.size()-1); 
      Label[atoi(curnode.c_str())]=atoi(nodelabel.c_str()); 
     } 
     catch(char* strerr) 
     { 
      failed=true; 
      break; 
     } 
    } 
    LabelFile.close(); 
} 

Giải pháp dự kiến: Sau khi xem xét ý kiến ​​và câu trả lời, tôi tin rằng mảng Dynamic C++ sẽ là lựa chọn tốt nhất, vì việc triển khai sẽ sử dụng các khóa dày đặc. Cảm ơn

Trả lời

10

Insertion cho unordered_map nên O (1) và thu hồi nên khoảng O (1), (nó về cơ bản một bảng băm).

timings của bạn như vậy là cách OFF, hoặc có cái gì đó WRONG với thực hiện hoặc sử dụng unordered_map của bạn.

Bạn cần cung cấp thêm một số thông tin và có thể cách bạn đang sử dụng vùng chứa.

Theo phần 6.3 n1836 sự phức tạp để chèn/retreival được đưa ra:

Một vấn đề bạn nên xem xét là việc thực hiện của bạn có thể cần phải liên tục được rehashing cấu trúc, như bạn nói bạn có 100mil + mục. Trong trường hợp đó khi tạo vùng chứa, nếu bạn có ý tưởng thô về số lượng "độc đáo" yếu tố sẽ được chèn vào vùng chứa, bạn có thể chuyển nó thành tham số cho hàm tạo và vùng chứa sẽ được khởi tạo tương ứng với bảng xô có kích thước phù hợp.

+0

có từ kinh nghiệm dict của tôi trong python một bảng băm nên được nhanh hơn so với một bản đồ dựa trên cây nhị phân, nhưng ít nhất là để chèn i am tìm bản đồ để được nhanh hơn unordered_map. –

+0

ya của nó có thể là rehashing sẽ dẫn đến tăng đáng kể trong thời gian cho insertions, kể từ khi tôi không cung cấp bất kỳ gợi ý về số lượng có thể của các yếu tố. –

+0

vì vậy nó được bảo đảm để được O (1) trên chèn hay không tôi không thể nói? Anh ta đã làm gì sai? – jokoon

1

unordered_map (ít nhất là trong hầu hết các triển khai) cho phép truy xuất nhanh, nhưng tốc độ chèn tương đối kém so với bản đồ. Một cây nói chung là tốt nhất khi dữ liệu được sắp xếp ngẫu nhiên, và lúc tồi tệ nhất khi dữ liệu được đặt hàng (bạn liên tục chèn vào một đầu của cây, tăng tần suất tái cân bằng).

Với tổng số 10 triệu mục, bạn có thể phân bổ một mảng đủ lớn và tìm kiếm nhanh - giả sử đủ bộ nhớ vật lý không gây ra sự cố, nhưng đó không phải là một lượng bộ nhớ khổng lồ tiêu chuẩn hiện đại.

Chỉnh sửa: có, vectơ về cơ bản là mảng động.

Chỉnh sửa2: Mã bạn đã thêm một số sự cố. while (! LabelFile.eof()) của bạn bị hỏng. Bạn thường muốn làm một cái gì đó như while (LabelFile >> inputdata) thay thế. Bạn cũng đang đọc dữ liệu hơi kém hiệu quả - những gì bạn mong đợi là hai con số được phân tách bằng một tab. Trong trường hợp đó, tôi sẽ viết vòng lặp giống như sau:

while (LabelFile >> node >> label) 
    Label[node] = label; 
+0

Vấn đề là tôi hy vọng sẽ mở rộng triển khai để xử lý có thể khoảng hàng tỷ mục. –

+0

Nó sẽ xử lý các mạng với tỷ + nút. Bản đồ chứa Nhãn cho mỗi nút trong mạng, mã sẽ được triển khai trên hadoop trong chế độ phát trực tuyến. –

+0

@Mitch: vâng, đó là chính xác những gì tôi đã nói. @akshayubha: câu hỏi không thực sự là số lượng mục, nhưng mật độ của các phím. Nếu đó là một tỷ khóa chạy từ 1 đến 1 tỷ, một mảng sẽ ổn. Nếu đó là một tỷ phím (nói) 128 bit, một mảng sẽ không hoạt động chút nào. –

2

Thời gian thêm tải unordered_map là do thay đổi kích thước mảng động. Lịch thay đổi kích thước là tăng gấp đôi số ô mỗi khi bảng vượt quá hệ số tải của nó. Vì vậy, từ một bảng trống, mong đợi các bản sao O (lg n) của toàn bộ bảng dữ liệu. Bạn có thể loại bỏ các bản sao bổ sung này bằng cách định kích thước bảng băm trả trước. Cụ thể

Label.reserve(expected_number_of_entries/Label.max_load_factor()); 

Chia bởi max_load_factor là tính đến các ô trống cần thiết cho bảng băm hoạt động.

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