2010-03-18 37 views
7

Theo sau từ một số previous question relating to heap usage restrictions, tôi đang tìm một lớp C++ chuẩn tốt để xử lý các mảng dữ liệu lớn theo cách vừa hiệu quả vừa hiệu quả về bộ nhớ. Tôi đã được phân bổ mảng bằng cách sử dụng một malloc duy nhất/HealAlloc nhưng sau nhiều trys bằng cách sử dụng các cuộc gọi khác nhau, tiếp tục rơi hôi của đống phân mảnh. Vì vậy, kết luận tôi đã đến, ngoài việc chuyển sang 64 bit, là sử dụng một cơ chế cho phép tôi có một mảng lớn bao trùm nhiều mảnh bộ nhớ nhỏ hơn. Tôi không muốn một phân bổ cho mỗi phần tử vì đó là bộ nhớ rất kém hiệu quả, vì vậy kế hoạch là viết một lớp ghi đè toán tử [] và chọn một phần tử thích hợp dựa trên chỉ mục. Đã có một lớp học phong nha ra khỏi đó để làm điều này, hay tôi tốt hơn lăn của riêng tôi?Lớp mảng C++ tốt để xử lý các mảng dữ liệu lớn một cách hiệu quả và nhanh chóng?

Từ hiểu biết của tôi và một số googling, quy trình Windows 32 bit về mặt lý thuyết có thể có địa chỉ tối đa 2GB. Bây giờ giả sử tôi đã cài đặt 2GB, và nhiều quy trình và dịch vụ khác đang hogging khoảng 400MB, bạn nghĩ chương trình của tôi có thể hợp lý như thế nào để nhận được từ heap?

Tôi hiện đang sử dụng các hương vị khác nhau của Visual C++.

Chỉnh sửa Theo bài đăng của Poita, tôi đã thử một số std :: deque, sử dụng kiểm tra sau trên VS2008;

#include <deque> 
using namespace std; 
struct V  
{ 
    double data[11]; 
}; 

struct T 
{ 
    long data[8];  
}; 


void dequeTest() 
{ 
    deque<V> VQ; 
    deque<T> TQ; 

    V defV; 
    T defT; 

    VQ.resize(4000000,defV); 
    TQ.resize(8000000,defT); 
} 

Tổng bộ nhớ cho dữ liệu trên đi ra ở 608MB, tôi có sử dụng thẳng malloc hoặc HeapAlloc và mất < 1 giây. Việc thay đổi kích thước deque mất 950MB ban đầu, và sau đó từ từ bắt đầu giảm trở lại. 15 phút sau, dequeTest() kết thúc, chỉ sử dụng 6MB bộ nhớ hiển thị cho quá trình mà có thể là nhiều hơn để làm với thời gian chạy. Tôi cũng đã cố gắng tạo ra các deque bằng cách sử dụng các tùy chọn push khác nhau, nhưng hiệu suất rất tệ, tôi phải thoát ra sớm. Tôi có thể có thể cung cấp một phân bổ tốt hơn so với defualt để có được một phản ứng tốt hơn nhiều, nhưng trên khuôn mặt của nó deque không phải là lớp học cho công việc này. Lưu ý điều này cũng có thể liên quan đến việc thực hiện MS VS2008 deque, như có vẻ là rất nhiều trong lớp này là rất thực hiện phụ thuộc khi nói đến hiệu suất.

Thời gian để viết lớp mảng lớn của riêng tôi, tôi nghĩ.

Chỉnh sửa thứ hai: Phân bổ số tiền nhỏ hơn mang lại 1.875GB ngay lập tức bằng cách sử dụng như sau;

#define TenMB 1024*1024*10 

void SmallerAllocs() 
{ 

    size_t Total = 0; 
    LPVOID p[200]; 
    for (int i = 0; i < 200; i++) 
    { 
     p[i] = malloc(TenMB); 
     if (p[i]) 
      Total += TenMB; else 
      break; 
    } 
    CString Msg; 
    Msg.Format("Allocated %0.3lfGB",Total/(1024.0*1024.0*1024.0)); 
    AfxMessageBox(Msg,MB_OK); 
} 

cuối cùng chỉnh sửa tôi đã quyết định chấp nhận bài Poita và các ý kiến ​​khác nhau sau đó, không phải vì tôi sẽ sử dụng lớp deque trực tiếp, nhưng nhiều hơn cho mảng như một cỗ bài khái niệm trong nhận xét tiếp theo. Điều này nên đơn giản để thực hiện với O (1) truy cập phần tử ngẫu nhiên, dựa trên một số phần tử cố định cho mỗi khối, đó là những gì tôi cần. Cảm ơn tất cả vì phản hồi!

+3

Tôi hy vọng không có "hương vị" nào trong số đó là VC6.0 –

+0

Trong khi tôi vẫn còn VC6.0 và sử dụng nó cho một số thứ, không phải bất cứ thứ gì xảy ra ở gần giai đoạn phát hành. Chủ yếu là VS2008, một số VS2003, và một số EVC + + 4.0 đó là lý do tại sao tôi cũng duy trì một VC6.0. –

+0

Chương trình cửa sổ 32 bit có thể phân bổ hơn 2GB bộ nhớ, bạn không thể ánh xạ tất cả cùng một lúc. - http://blogs.msdn.com/oldnewthing/archive/2004/08/10/211890.aspx – Bill

Trả lời

11

Bạn đã thử sử dụng một số std::deque? Không giống như std::vector, sử dụng một phân bổ đống lớn, deque thường được phân bổ theo các đoạn nhỏ, nhưng vẫn cung cấp chỉ số thời gian liên tục được phân bổ qua operator[].

+0

Tôi sẽ xem xét triển khai thực hiện deque nhưng tôi sẽ lo lắng về việc khối lượng nhỏ như thế nào. Tôi đang đối phó với hàng triệu cấu trúc tương đối nhỏ, do đó, bất kỳ việc triển khai nào phân bổ bộ nhớ riêng lẻ trên cơ sở mỗi mục phải chịu trách nhiệm về bộ nhớ không hiệu quả. –

+0

Tôi không biết nó sử dụng chính sách nào để định kích thước, nhưng nó chắc chắn là nhiều hơn 1. Tôi nghi ngờ hiệu suất bộ nhớ sẽ lớn hơn 10%, và tôi mong đợi nó là <5%. –

+0

Sau khi đọc lên trên std :: deque, cụ thể về việc sử dụng các trình phân bổ, tôi không thể tìm thấy bất cứ điều gì nói rằng nó sẽ không cố gắng phân bổ tất cả bộ nhớ trong một khối liền kề duy nhất. Xem http://www.cplusplus.com/reference/std/memory/allocator/ Nói cách khác, tôi không thể tìm thấy bất cứ điều gì để gợi ý rằng thêm 1GB dữ liệu vào một deque là bất kỳ khả năng thành công hơn bằng cách sử dụng một HeapAlloc để Làm điều tương tự. Bạn có bất kỳ tài liệu tham khảo để đề nghị rằng một deque sẽ sử dụng nhiều phân bổ đống cho số lượng rất lớn của dữ liệu, và nếu như vậy làm thế nào nó phân mảnh chúng? –

3

Từ quan điểm của chương trình, bạn luôn có sẵn 2GB khi khởi động, bất kể có vấn đề gì khác xảy ra trong hệ thống. Tôi không tin rằng Windows cung cấp một cách để phát hiện nếu bạn có bộ nhớ được phân trang ra đĩa hay không. Theo như bạn cấu trúc dữ liệu đi, có vẻ như bạn đang mô tả một cái gì đó tương tự như cách một deque được thực hiện trong STL.

+0

Tôi nghĩ bạn có nghĩa là deque (http://www.cplusplus.com/reference/stl/deque/), chứ không phải dequeue. – Bill

+0

Đúng vậy. Đã sửa. – tloach

4

Chính xác mức độ thưa thớt của mảng này? Nếu có một lượng lớn không gian trống (không sử dụng) trong đó, bạn có thể muốn có cách tiếp cận khác. Các answer to this question cho thấy một bản đồ stl.

Nếu nó không thưa thớt (như đã đề cập trong các nhận xét), một điều bạn có thể xem xét vì bạn đang chạy trên Windows đang sử dụng memory-mapped file. Mặc dù hệ điều hành của bạn có thể là 32-bit, nhưng hệ thống tệp của bạn thì không. Điều này tất nhiên có nghĩa là sẽ có trao đổi xảy ra mặc dù, đó là trách nhiệm được khá chậm hơn một chút so với nếu bạn thực sự có thể đặt toàn bộ điều darn trong RAM.

Ngoài ra, bạn thực sự nên xem xét việc loại bỏ RAM của hệ thống lên đến mức tối đa (3GB trên Windows 32 bit mà tôi tin) để xem có khắc phục được sự cố cho bạn hay không. Điều đó chỉ nên chi phí cho bạn khoảng 100 đô la, và bạn đang chi tiêu nhiều hơn thế trong giờ làm việc chỉ lo lắng về điều này.

+0

Không có không gian không sử dụng nào cả. Dữ liệu được đề cập là mạng TIN bao gồm các tọa độ 3d và hình tam giác liên kết chúng với nhau, cùng biểu diễn một bề mặt không đều lớn. Cảm ơn bạn đã liên kết trong mọi trường hợp, cũng có thể hữu ích ở nơi khác. –

+1

Có 2GB cài đặt! = 2GB ram vật lý có sẵn. Ngay cả với 4GB cài đặt bạn có thể không có nhiều hơn 2.5gb cài đặt nếu bạn có một card đồ họa bộ nhớ lớn (nếu bạn đang làm công việc 3D thì đây là một khả năng khác biệt). Cá nhân đảm bảo bạn đã cài đặt 4 + GB và hệ điều hành 64 bit. –

+1

@graham - Anh ta đã nói anh ta đang sử dụng hệ điều hành 32 bit, và hỏi anh ta có thể làm gì để nâng cấp lên 64bit. Đó là lý do tại sao tôi đề nghị lên tới 3GB. Điều đó đang được nói, tôi đồng ý rằng sử dụng một hệ điều hành 64-bit có lẽ sẽ là một giải pháp tốt (và tương đối rẻ). –

1

std :: deque thực hiện chính xác những gì bạn mô tả, nhưng thường ở mức độ chi tiết của kích thước trang OS (có nghĩa là, khối mà nó phân bổ thường là 4 kB).

Nếu bạn không hài lòng với hiệu suất mặc định của deque, bạn có thể viết trình phân bổ tùy chỉnh lấy khối lớn hơn - tức là, nhận được 1 MB trở lên cùng một lúc.

Như những người khác đã nói, không gian địa chỉ ảo của quy trình hoàn toàn độc lập với tất cả các quy trình khác, vì vậy bạn có thể giải quyết 2 GB bất kể vấn đề gì đang xảy ra trong hệ thống của bạn. Hệ điều hành sẽ hoán đổi các trang bộ nhớ của bạn đến/từ đĩa khi cần thiết để phù hợp với các ràng buộc về số lượng bộ nhớ được cài đặt và tất cả các quy trình cạnh tranh cho nó. Điều này sẽ xảy ra ở kích thước trang 4 kB, độc lập với khối lượng lớn của bạn.

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