2010-03-31 39 views
5

Có ai có tài nguyên về hướng dẫn tối ưu hóa bộ nhớ C++ không? Các phương pháp hay nhất, điều chỉnh, v.v ...?Nguyên tắc tối ưu hóa hiệu suất/bộ nhớ C++

Như một ví dụ:

Class xxx { 

    public: 
     xxx(); 
     virtual ~xxx(); 

    protected: 

    private: 

}; 

Nên có bất kỳ lợi ích trên trình biên dịch hoặc cấp phát bộ nhớ để thoát khỏi protected and private vì có không có mặt hàng được bảo vệ và tư nhân trong lớp này?

UPDATE: Những gì được một lập trình viên thực hiện điều này:

Class xxx { 

    public: 
     xxx(); 
     virtual ~xxx(); 

    public: 
     more stuff(); 
     more(); 

    ifndef __BUILD_WIN__ 
     public: 
     even more(); 
     envenmore2(); 
    endif 
    protected: 

    private: 

}; 
+0

Bạn có thể thêm bất kỳ thông tin nào về miền sự cố bạn đang làm việc không? – mch

Trả lời

12

Có ai có một nguồn lực cho hướng dẫn bộ nhớ tối ưu hóa C++? Các phương pháp hay nhất, điều chỉnh, v.v ...?

Điều đó phụ thuộc rất nhiều vào cả môi trường trình biên dịch và môi trường đích của bạn (RISC, Unix/Linux, Windows). Hầu hết các trình biên dịch sẽ có thông tin như vậy.

Có các tiện ích ngoài đó cho phép bạn theo dõi rò rỉ bộ nhớ để bạn có thể khắc phục chúng trong khi kiểm tra. Nếu bạn định tự động phân bổ rất nhiều thứ (thường là trường hợp với C/C++), hãy cố gắng chắc chắn rằng bạn xử lý tất cả mọi thứ trước khi phá hủy một đối tượng. Để thực hiện việc này:

  • Nếu bạn coi trọng bộ nhớ trên bộ xử lý, hãy sử dụng smart pointers.
  • Nếu lớp học của bạn có bất kỳ biến thành viên nào là con trỏ, hãy đảm bảo rằng hàm hủy của bạn giải phóng mỗi một biến. Nhóm các biến thành viên của bạn lại với nhau trên mã nguồn của bạn để dễ dàng so sánh các biến đó với hàm hủy.
  • Tránh phân bổ bộ nhớ động bất cứ khi nào có thể để tránh rò rỉ. Thích std::string trên động phân bổ char* vv

Nên có bất kỳ lợi ích trên trình biên dịch hoặc bộ nhớ phân bổ để có được thoát khỏi protected and private kể từ có không có các chỉ tiêu protected and private trong lớp học này?

Không, nếu tôi không nhầm, bảo vệ/riêng tư chỉ được kiểm tra trong quá trình biên dịch, vì vậy chúng không ảnh hưởng đến hiệu suất ngay cả khi có các mục trong từ khóa.

Hơn nữa, điều quan trọng là phải hiểu rằng trình biên dịch là rất inteligent (thường là nhiều hơn các lập trình viên) vì vậy nó sẽ tối ưu hóa đi bất cứ điều gì nó có thể; Ví dụ, chúng ta hãy khai báo một biến, int a, bên trong hàm tạo của bạn. Và giả sử bạn không sử dụng nó, bạn chỉ quên nó ở đó. Hầu hết các trình biên dịch thậm chí sẽ không tiết kiệm không gian ngăn xếp cho các biến đó. Những người khác sẽ cần người dùng kích hoạt Tối ưu hóa để điều này xảy ra, nhưng như một quy tắc-ngón tay cái, phiên bản sản xuất của bất kỳ chương trình nào sẽ được biên dịch với tối ưu hóa được kích hoạt, ngay cả khi không đầy đủ.

Về bản cập nhật, mà điều bạn nhìn là pre-vi xử lý chỉ thị và đang được sử dụng để làm những gì được gọi là chọn lọc biên soạn. Hãy xem here.

+0

@bruno - cảm ơn, hữu ích. trình biên dịch thông minh hơn các lập trình viên, nhưng các lập trình viên viết các trình biên dịch, vì vậy ít nhất một vài * lập trình viên phải đủ thông minh để làm cho trình biên dịch làm tất cả điều này! Bây giờ để xem cách XCode sẽ cho tôi biết về các mặt hàng không sử dụng vì nó sẽ là tốt để biết! –

+2

@ML: Tôi chưa bao giờ sử dụng XCode (đó là một IDE được Apple nhắm mục tiêu, phải không?) Nhưng có lẽ có nhiều cách để thực hiện nó. Trình biên dịch nắm giữ kiến ​​thức của nhiều lập trình viên hàng đầu, đó là lý do tại sao chúng thông minh hơn lập trình viên trung bình. Kasparov là người chơi cờ tướng giỏi nhất, nhưng bị đánh bại bởi một phần mềm do mọi người tạo ra! (và đó là những gì tôi thích về máy tính, mặc dù tôi muốn Kasparov có thể outsmart DeepBlue). –

+0

Trình biên dịch chỉ "thông minh hơn" so với người lập trình bởi vì họ có thể xem xét nhiều tối ưu hóa cùng một lúc dễ dàng hơn nhiều so với con người. Việc tối ưu hóa riêng lẻ có thể không khó, nhưng nhất quán áp dụng tất cả chúng cùng một lúc. – mskfisher

2

Vâng trình biên dịch sẽ không phải phân tích cú pháp chúng, vì vậy có lợi ích cho trình biên dịch. Đối với những gì có giá trị (không phải rất nhiều).

Không có sự khác biệt về sử dụng bộ nhớ.

Ngoài ra, lợi ích duy nhất tôi có thể nghĩ là có ít cruft cho ai đó đọc mã phải đối phó với (không phải là nó đặc biệt nặng nề trong ví dụ của bạn).

+0

Tôi cũng đồng ý rằng việc đọc mã dễ dàng hơn nếu bạn sử dụng các từ khóa không cần thiết. –

1

từ khóa công cộng, được bảo vệ và riêng tư, không biến nó thành tệp đối tượng, vì vậy không có lợi ích gì cả.

Nói chung

  • Cố gắng tránh việc phân bổ và giải phóng bộ nhớ, tái sử dụng bất cứ khi nào có thể. Đi bộ đống là đặc biệt chậm.
  • Bộ nhớ miễn phí khi bạn kết thúc. Đừng bỏ qua xung quanh trừ khi có những lý do hiệu suất mạnh mẽ để làm như vậy.

Sự thật là, không giống như Java, khi lập trình bằng C++, bạn luôn cần phải suy nghĩ về quản lý bộ nhớ để tránh rò rỉ. Do đó, tối ưu hóa tự nhiên hơn là nói Java

+3

@deus Tôi hầu như không bao giờ nghĩ về quản lý bộ nhớ khi tôi lập trình bằng C++. –

+2

Nên đọc: "Sự thật là, không giống Java, C++ cho phép bạn viết và sử dụng trình bao bọc để cung cấp cho bạn khả năng quản lý bộ nhớ tự động xác định, vì vậy bạn không bao giờ cần phải suy nghĩ về quản lý bộ nhớ để tránh rò rỉ". – GManNickG

0

Theo như hướng dẫn chung, có What Every Programmer Should Know About Memory, nhưng tôi không chắc đó là những gì bạn đang tìm kiếm.

Một hướng dẫn chung để tối ưu hóa bộ nhớ bên trong một cấu trúc hoặc lớp học là đặt hàng các thành viên dữ liệu của bạn từ lớn nhất đến nhỏ nhất. Điều này ngăn cản padding dư thừa từ không gian lãng phí trong cấu trúc hoặc lớp học của bạn.

Đối với câu hỏi của bạn, tôi nghĩ rằng câu trả lời đó được trả lời phù hợp, nhưng bạn có thể so sánh bản thân bằng cách sử dụng sizeof().

0

Sẽ có bất kỳ lợi ích nào trên trình biên dịch hoặc phân bổ bộ nhớ để loại bỏ bảo mật và riêng tư vì không có mục nào được bảo vệ và riêng tư trong lớp này?

No. AFAIK, các phương pháp không ảo không làm tăng kích thước của cá thể lớp.

Có ai có tài nguyên về hướng dẫn tối ưu hóa bộ nhớ C++ không?

1) Nếu bạn lo ngại về hiệu suất, hãy sử dụng profiler (ví dụ: AQtime). Đừng đoán, sử dụng các công cụ.
2) Nói chung, không thường xuyên là ý tưởng hay (một số _millions_ lần mỗi giây) cấp phát và phân bổ bộ nhớ (sử dụng mới/xóa), đặc biệt là các khối lớn. Theo kinh nghiệm của tôi, kết quả sử dụng như vậy mất hiệu suất. Nếu bạn thường xuyên cần phân bổ khối bộ nhớ lớn với cùng một thường trình (sử dụng new hoặc std :: vector), hãy xem xét sử dụng lại cùng một khối trong cuộc gọi tiếp theo (điều này sẽ khó khăn trong ứng dụng đa luồng). I E.thay vì

void doStuff(int memSize){ 
    std::vector<char> buf(memSize); 
    //..some code here 
} 

một cái gì đó sử dụng như thế này:

void doStuff(int memSize){ 
    static std::vector<char> buf; 
    if (buf.size() < memSize) 
     buf.resize(memSize); 
    //..some code here 
} 

Nhưng chỉ khi cần thiết và chỉ khi bạn hoàn toàn chắc chắn rằng thói quen này không thể được gọi từ một số chủ đề riêng biệt cùng một lúc. (Để làm cho nó tương thích đa luồng, bạn sẽ cần một số thủ thuật - hoặc mutexes, hoặc "pool" của nhiều bộ đệm)
3) Phân bổ hơn 1 megabyte (cho windows) hoặc 8 megabyte (cho Linux) trên stack gây ra chương trình của bạn để sụp đổ (ngăn xếp tràn để giành chiến thắng, segfault trên Linux), trừ khi bạn có quy định kích thước ngăn xếp trong thời gian biên dịch. Ví dụ:

void doStuff(){ 
    char buf[1024*1024*12];//use new[] or std::vector instead of this. 
    //some code here 
} 

Đó là tất cả những gì tôi có thể nghĩ đến.

0

Nó thực sự phụ thuộc vào ứng dụng của bạn. Nếu bạn đang làm mô phỏng hay bất kỳ loại máy tính khoa học nào mà bạn đang thực hiện các phép tính dấu chấm động trên các mảng lớn của bộ nhớ thì có rất nhiều thứ bạn có thể làm.

  • Optimize để tái sử dụng bộ nhớ cache (bộ nhớ cache chặn, đệm, vv)
  • Optimize để giảm thiểu TLB lượt truy cập (Sửa lỗi)
  • Sắp xếp dữ liệu của bạn như cấu trúc của mảng, không phải là mảng các cấu trúc
  • Tránh bộ nhớ không cần thiết xóa
  • Tránh việc phân bổ lại bộ nhớ, tái sử dụng thay vì

Nếu bạn cần phải có nhiều đối tượng nhỏ, nhìn vào những thứ như mẫu thiết kế cân bằng hoặc các hồ đối tượng.

Vì lo lắng về các tờ khai privateprotected, đừng. Chúng chỉ liên quan đến việc biên dịch để thực thi đóng gói và ẩn dữ liệu, và không ảnh hưởng đến nhị phân được tạo ra.

0

Kỹ thuật Tối ưu hóa Có ba loại kỹ thuật để tối ưu hóa mã trong C:

Tính-bound kỹ thuật kỹ thuật Memory-bound Input/Output-bound kỹ thuật

kỹ thuật Tính-bound liên quan đến máy tính thời gian thực hiện để thực hiện các toán tử và hàm. kỹ thuật tính toán-bound bao gồm:

Profiling nội tuyến Vòng unrolling Vòng gây nhiễu bất biến vòng tính toán Vòng đảo ngược Tail loại bỏ đệ quy Bảng tra cứu

Trong tính toán bộ nhớ bị ràng buộc, bạn cần phải đưa vào tài khoản bộ nhớ mà chương trình sử dụng. Việc sử dụng bộ nhớ từ các phần dưới của phân cấp bộ nhớ làm tăng thời gian thực hiện. Bạn cần sử dụng bộ nhớ từ cấp độ thích hợp trong khi chạy chương trình.kỹ thuật bộ nhớ-bound bao gồm:

Địa phương quy chiếu Row-chính giải quyết Padding giảm rò rỉ bộ nhớ

Trong Input/Output (I/O) ràng buộc tối ưu hóa, việc tiếp cận tuần tự và truy cập ngẫu nhiên phương pháp được sử dụng để giảm thời gian cần thiết để lấy thông tin.

I/O được lưu vào bộ đệm nhanh hơn I/O không được lọc. Bạn có thể sử dụng các hàm read() và write() với các bộ đệm lớn. Bạn có thể sử dụng mmap() để giảm thời gian cần thiết để truy xuất thông tin. Mmap() ánh xạ không gian địa chỉ của tiến trình với bộ nhớ hoặc tệp được chia sẻ.

một số kỹ thuật tối ưu hóa khác là:

Giảm thiểu việc sử dụng các biến toàn cầu trong chương trình.

Khai báo tất cả các chức năng khác với các biến chung dưới dạng tĩnh trong tệp.

Sử dụng các biến kích thước từ như int và float thay vì char, short và double.

Tránh sử dụng đệ quy.

Tránh sử dụng hàm sqrt() vì nó là CPU chuyên sâu.

Sử dụng mảng một chiều.

Không chia các chức năng liên quan chặt chẽ thành các tệp riêng biệt.

Sử dụng hàm puts() thay cho hàm printf.

Sử dụng truy cập tệp không định dạng/tệp nhị phân thay vì truy cập tệp được định dạng.

Sử dụng mallopt() nếu trình biên dịch hỗ trợ chức năng này để kiểm soát chức năng malloc.

Sử dụng macro thay vì các chức năng nhỏ để tiết kiệm thời gian CPU.