2010-11-04 34 views
11

Tôi có một chương trình sử dụng rất nhiều std::map. Trong Windows, nhiều bộ nhớ hơn được sử dụng như dưới Linux. Có ai có ý tưởng tại sao điều này xảy ra không?sử dụng bộ nhớ cấu trúc dữ liệu STL, cửa sổ so với linux

Linux: Last process took 42.31 s and used not more than 909 MB (RSS 900 MB) of memory

Windows: Last process took 75.373 s and used not more than 1394 MB (RSS 1395 MB) of memory

tôi sử dụng gcc 4.4.3 và trình biên dịch C++ VS 2010 trên dòng lệnh, với các thiết lập phát hành.

EDIT: Xin lỗi vì trả lời những câu hỏi mà muộn ...

Mã này trông như thế này:

enum Symbol { 
    ... 
} 

class GraphEntry { 

    public: 

    ... 

    virtual void setAttribute (Symbol name, Value * value) = 0; 

    const Value * attribute (Symbol name) const; 

    private: 

    std::map<Symbol, Attribute> m_attributes; 
}; 

class Attribute { 

    public: 

    Attribute (Symbol name, Value * val); 

    ... 

    Symbol name() const; 

    Value * valuePointer() const; 

    void setValuePointer (Value * p); 

    private: 

    Symbol m_name; 

    Value * m_value; 
}; 

class Graph : public GraphEntry { 

    ... 

    public: 

    Node * newNode (...); 

    Graph * newSubGraph (...); 

    Edge * newEdge (...); 

    ... 

    setSomeAttribute (int x); 

    setSomeOtherAttribute (float f); 

    ... 

    private: 

    std::vector<GraphEntry *> m_entries; 
}; 

Toàn bộ điều mô tả một cấu trúc đồ thị, có thể tổ chức một số thuộc tính trên các nút của nó và các cạnh. Value chỉ là một lớp cơ sở và các lớp dẫn xuất có thể chứa các giá trị với các loại tùy ý, như int hoặc std::string.

EDIT 2: Dưới Windows, tôi sử dụng những lá cờ sau: -DRELEASE -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_OUTPUT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX /O2 /MD /Gy /EHsc

EDIT 3: Việc sử dụng bộ nhớ được đọc từ một tập tin/proc dưới Linux (như memuse). Trong Windows, một số hàm WinAPI được gọi, nhưng tôi không phải là chuyên gia cho điều này, vì vậy đó là tất cả những gì tôi có thể nói về nó.

EDIT 4: Sử dụng /GS--D_SECURE_SCL kết quả trong Last process took 170.281 s and used not more than 1391 MB (RSS 1393 MB) of memory

+0

Bạn đang sử dụng Visual Studio? Nếu có, phiên bản nào? Bạn đang gỡ lỗi? – msandiford

+1

Bạn đo mức sử dụng bộ nhớ như thế nào? – camh

+8

Mã hoặc nó không xảy ra. – Puppy

Trả lời

8

Bạn sẽ quan sát việc sử dụng bộ nhớ trên Windows ở đâu đó lớn hơn từ 1 đến 2 lần. Heap thuật toán sang một bên, Windows malloc(), và sau đó bất kỳ cấu trúc dữ liệu được phân bổ trên heap qua new (chẳng hạn như các nút của std::map với kiểu phân bổ mặc định), được căn chỉnh đến 16 byte. Trên Linux, glibc defaults to 8 byte alignment. Giả sử một số mịn trong sự khác biệt do phân mảnh, tối ưu hóa gặt hái các trang không sử dụng, vv bạn có thể mong đợi sự khác biệt để trở nên ít rõ ràng hơn

Kiểm tra nhanh mã của bạn và loại giá trị phải là 4 và 8 byte tương ứng (SymbolAttribute). Chúng sẽ làm tròn tới 8 byte trên Linux và 16 byte trên Windows. Bạn nên có số lượng nút bản đồ bằng nhau, ít nhất là trong việc triển khai MSVC, các giao diện này tiêu thụ tối thiểu 22 byte, MSVC sẽ mở rộng thành 32 do quy tắc căn chỉnh thành viên, cũng là mức chi tiết malloc của nó. GCC sẽ mở rộng thành 24, nghĩa là tổng cộng xấp xỉ 48 byte trong MSVC đến GCC/Linux '32 cho mỗi nút. Sử dụng bộ nhớ nhiều hơn 50% trên Windows.

Dưới đây là cấu trúc nút sử dụng trong MSVC, tôi có thể tra cứu GCC tương đương nếu bạn quan tâm:

struct _Node 
    { // tree node 
    _Nodeptr _Left; // left subtree, or smallest element if head 
    _Nodeptr _Parent; // parent, or root of tree if head 
    _Nodeptr _Right; // right subtree, or largest element if head 
    value_type _Myval; // the stored value, unused if head 
    char _Color; // _Red or _Black, _Black if head 
    char _Isnil; // true only if head (also nil) node 

Tôi sẽ thêm cho những ai không quen với cách thức hoạt động sử dụng bộ nhớ, có một số yếu tố tại chơi:

  • Bộ nhớ được cấp phát theo khối làm tròn lên đến bội số tiếp theo của căn chỉnh cho cơ chế phân bổ được sử dụng. Đối với heap, các quy tắc liên kết malloc() đang được sử dụng (trừ khi bạn phá hủy heap thông thường hoặc sử dụng một số cấp phát khác so với mặc định).
  • Bộ nhớ ảo được "cung cấp" bởi hệ thống theo các phần được gọi là các trang, bội số nguyên của kích thước khung hình, nằm ngoài phạm vi của câu hỏi này. Điều này có ảnh hưởng nhỏ đến câu trả lời, vì việc sử dụng bộ nhớ quá lớn so với kích thước trang được đề cập (4K) và kích thước trang lần lượt lớn so với các sắp xếp sử dụng (8 và 16).
+0

Tôi nên thêm thời gian chạy tăng lên trên Windows là sự kết hợp của kích thước tăng của cấu trúc, có nghĩa là ít bộ nhớ đệm hơn có thể xảy ra và sự khác biệt tối ưu hóa lệnh trong trình biên dịch được sử dụng. –

+0

Cảm ơn câu trả lời của bạn. Thời gian chạy tăng lên cũng do máy chậm hơn được sử dụng để phát triển cửa sổ. – swegi

0

Bạn đã thực hiện kiểm tra trong phiên bản hoặc chế độ gỡ lỗi dưới cửa sổ? STL trong chế độ gỡ lỗi thực hiện rất nhiều kiểm tra thêm; có lẽ nó cũng sử dụng nhiều bộ nhớ hơn để có thể thực hiện tất cả các kiểm tra.

+0

Tôi sử dụng chế độ phát hành – swegi

0

Đối với VC++, hãy thử sử dụng/chuyển đổi dòng lệnh GS.

6

Một số phiên bản VC++ cũng sử dụng các trình vòng lặp được kiểm tra (_SECURE_SCL) trong bản phát hành bản phát hành. VC2005VC2008 bật chúng theo mặc định. VC2010 vô hiệu hóa chúng by default

Tùy thuộc vào trình biên dịch của bạn, đó có thể là một điều khác cần kiểm tra (và tắt).

+1

+1. Điều này giải quyết nó cho tôi khi tôi được gọi để giải quyết một trường hợp simular. – Sjoerd

+1

@swegi: hãy bình luận về việc liệu điều này có áp dụng cho bạn hay không, và nếu như vậy bộ nhớ được so sánh như thế nào sau đó ... –

7

Mỗi trình biên dịch được vận chuyển với thực hiện riêng của STL, do đó bạn đang so sánh:

  • GCC STL + Linux thói quen phân bổ
  • VC++ STL + Windows thói quen phân bổ

Nó khá khó khăn để vẽ một so sánh có ý nghĩa ở đây bởi vì bạn không biết việc phân bổ thường xuyên hoặc thực thi STL (hoặc có thể cả hai) thực sự có trách nhiệm.

Tôi cho rằng bạn không so sánh chương trình 32 bit với chương trình 64 bit vì điều này thậm chí còn ít ý nghĩa hơn.

+0

Cả hai hệ thống đều là 32bit. – swegi

0

Khi bạn nói bộ nhớ được sử dụng là "không nhiều hơn", bạn đang đề cập đến việc sử dụng bộ nhớ cao điểm hoặc mức sử dụng bộ nhớ trung bình trong suốt thời gian tồn tại của ứng dụng?

Đảm bảo bộ nhớ được ứng dụng của bạn sử dụng 'mới' hoặc 'malloc' hoặc bất kỳ cuộc gọi thư viện cấp phát bộ nhớ nào khác được trả về bằng cách sử dụng 'xóa' hoặc 'miễn phí' hoặc bất kỳ cuộc gọi thư viện nào tương đương.

Trong Linux, bạn có thể sử dụng valgrind và kiểm tra rò rỉ bộ nhớ.

+0

Sử dụng bộ nhớ cao nhất – swegi

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