2009-09-09 29 views
14

Gần đây, một đồng nghiệp đã chỉ ra rằng việc biên soạn mọi thứ thành một tệp duy nhất tạo ra mã hiệu quả hơn nhiều so với việc biên dịch các tệp đối tượng riêng biệt - ngay cả khi tối ưu hóa thời gian liên kết được bật. Ngoài ra, tổng thời gian biên dịch cho dự án đã giảm đáng kể. Cho rằng một trong những lý do chính để sử dụng C++ là hiệu quả mã, điều này gây ngạc nhiên cho tôi.Tại sao tối ưu hóa trình liên kết lại quá nghèo nàn?

Rõ ràng, khi trình lưu trữ/liên kết tạo thư viện ra khỏi tệp đối tượng hoặc liên kết chúng thành một tệp tối ưu hóa có thể thực thi, thậm chí đơn giản sẽ bị phạt. Trong ví dụ dưới đây, nội tuyến trival chi phí 1,8% về hiệu suất khi được thực hiện bởi trình liên kết thay vì trình biên dịch. Có vẻ như công nghệ trình biên dịch phải được nâng cao đủ để xử lý các tình huống khá phổ biến như thế này, nhưng nó không xảy ra.

chỉnh sửa:

Đây là một ví dụ đơn giản sử dụng Visual Studio 2008:

#include <cstdlib> 
#include <iostream> 
#include <boost/timer.hpp> 

using namespace std; 

int foo(int x); 
int foo2(int x) { return x++; } 

int main(int argc, char** argv) 
{ 
    boost::timer t; 

    t.restart(); 
    for (int i=0; i<atoi(argv[1]); i++) 
    foo (i); 
    cout << "time : " << t.elapsed() << endl; 

    t.restart(); 
    for (int i=0; i<atoi(argv[1]); i++) 
    foo2 (i); 
    cout << "time : " << t.elapsed() << endl; 
} 

Foo.cpp

int foo (int x) { return x++; } 

kết quả chạy: 1,8% đạt hiệu suất sử dụng liên kết foo thay của inline foo2.

$ ./release/testlink.exe 100000000 
time : 13.375 
time : 13.14 

Và có, các cờ tối ưu hóa liên kết (/ LTCG) đang bật.

+4

Trình biên dịch nào bạn đang sử dụng? VC++ có một tùy chọn gọi là Toàn bộ chương trình tối ưu hóa mà tôi tin rằng sẽ làm những gì bạn đang yêu cầu. –

+0

Hầu hết các biên dịch hiện đại đều có tùy chọn "tối ưu hóa thời gian liên kết", nhưng nó thường được chọn tham gia vì nó làm chậm đáng kể liên kết. Bạn đã bật nó trong thử nghiệm chưa? Nó thường cho phép nội suy xuyên đối tượng, trong số những thứ khác. –

+0

Một trong những lý do chính cho C++ là * mã nguồn * hiệu quả mã; để áp dụng đối số này cho mã đối tượng là rất quan trọng. – harpo

Trả lời

3

Tôi không phải là chuyên gia biên dịch, nhưng tôi nghĩ trình biên dịch có nhiều thông tin hơn để tối ưu hóa khi nó hoạt động trên cây ngôn ngữ, như được chọn cho mối liên kết có nội dung để hoạt động trên đầu ra đối tượng, ít biểu cảm hơn mã trình biên dịch đã thấy. Do đó ít nỗ lực hơn được chi tiêu bởi các nhóm phát triển và trình biên dịch (devlopment team) vào việc làm cho các phép opter liên kết có thể phù hợp, theo lý thuyết, các thủ thuật mà trình biên dịch thực hiện.

BTW, tôi xin lỗi tôi đã phân tâm câu hỏi ban đầu của bạn vào cuộc thảo luận ltcg, bây giờ tôi hiểu câu hỏi của bạn hơi khác một chút, quan tâm hơn đến thời gian liên kết so vớibiên dịch tối ưu hóa thời gian tĩnh có thể/có sẵn.

+0

Điều này không đúng đối với Visual C++. Khi biên dịch với/GL và liên kết với/LTCG, trình biên dịch tạo ra một biểu diễn trung gian trong các tệp đối tượng thay vì mã máy thực tế và trình liên kết lấy biểu diễn trung gian đó và thực hiện biên dịch thực tế. –

27

Đồng nghiệp của bạn đã lỗi thời. Công nghệ này đã ở đây từ năm 2003 (trên trình biên dịch MS C++): /LTCG. Liên kết tạo mã thời gian là đối phó với chính xác vấn đề này. Từ những gì tôi biết, GCC có tính năng này trên radar cho trình biên dịch thế hệ tiếp theo.

LTCG không chỉ tối ưu hóa mã như chức năng nội tuyến trên mô-đun, nhưng thực sự sắp xếp lại mã để tối ưu hóa vị trí bộ đệm và phân nhánh cho tải cụ thể, xem Profile-Guided Optimizations. Các tùy chọn này thường được dành riêng cho bản phát hành Bản phát hành vì bản dựng có thể mất hàng giờ để hoàn thành: sẽ liên kết một tệp có thể thực thi, chạy tải hồ sơ và sau đó liên kết lại với kết quả lược tả. Các liên kết chứa các chi tiết về chính xác những gì được tối ưu hóa với LTCG:

nội tuyến - Ví dụ, nếu có tồn tại một hàm Một thường xuyên gọi hàm B, và chức năng B là tương đối nhỏ, sau đó profile- hướng dẫn tối ưu hóa sẽ inline chức năng B chức năng A.

ảo gọi Đầu cơ - Nếu một cuộc gọi ảo , hoặc gọi số khác thông qua một con trỏ chức năng, thường xuyên nhắm mục tiêu chức năng nhất định, tối ưu hóa hướng dẫn hồ sơ có thể chèn cuộc gọi trực tiếp có điều kiện lên chức năng được nhắm mục tiêu thường xuyên và cuộc gọi trực tiếp có thể được gạch chân.

Đăng ký phân bổ - Tối ưu hóa với kết quả dữ liệu hồ sơ trong phân phối đăng ký tốt hơn .

Basic Khối Tối ưu hóa - khối cơ bản tối ưu hóa cho phép phổ biến thực hiện khối cơ bản mà tạm thời thực hiện trong một khung cho được đặt trong cùng một bộ trang (địa phương). Điều này giảm thiểu số trang được sử dụng, do đó giảm thiểu chi phí bộ nhớ.

Size/Speed ​​Optimization - Chức năng nơi chương trình dành rất nhiều thời gian có thể được tối ưu hóa cho tốc độ.

Chức năng Layout - Dựa trên các cuộc gọi đồ thị và lưu hồ sơ người gọi/callee hành vi, chức năng mà có xu hướng dọc theo con đường thực hiện tương tự là đặt trong phần tương tự.

Conditional Chi nhánh Tối ưu hóa - Với thiết bị thăm dò giá trị, hồ sơ-hướng dẫn tối ưu hóa có thể tìm thấy nếu một cho giá trị trong một câu lệnh switch được sử dụng thường xuyên hơn các giá trị khác. Giá trị sau đó có thể được rút ra khỏi câu lệnh chuyển đổi . Điều tương tự có thể được thực hiện với các hướng dẫn if/else nơi trình tối ưu hóa có thể đặt hàng nếu/else khác rằng khối if hoặc else được đặt trước tùy thuộc vào khối nào thường xuyên hơn.

Mã Chết Tách - Mã đó là không được gọi trong hồ sơ được chuyển đến một phần đặc biệt mà được gắn đến cuối của bộ phận. Điều này có hiệu quả giữ phần này trong số các trang thường được sử dụng.

EH Mã Tách - Mã EH, được đặc biệt thực hiện, có thể thường được di chuyển đến một phần riêng khi tối ưu hóa thông tin dẫn đường có thể xác định rằng các trường hợp ngoại lệ xảy ra chỉ về điều kiện đặc biệt.

Memory Intrinsics - Việc mở rộng intrinsics thể được quyết định tốt hơn nếu nó thể được xác định nếu một bên là gọi thường xuyên. Một nội tại có thể cũng được tối ưu hóa dựa trên khối kích thước di chuyển hoặc bản sao.

+4

Về hỗ trợ gcc, hãy xem http://gcc.gnu.org/wiki/LinkTimeOptimization –

+0

Cảm ơn bạn đã liên kết Pavel –

+0

Tạo mã thời gian liên kết chậm hơn việc biên dịch thành một tệp. –

1

đồng nghiệp của bạn thông minh hơn hầu hết chúng ta. Ngay cả khi nó có vẻ là một cách tiếp cận thô sơ lúc đầu, dự án nội tuyến thành một tệp .cpp đơn lẻ có một điều mà các cách tiếp cận khác như tối ưu hóa thời gian liên kết không có và sẽ không có trong thời gian - độ tin cậy

Tuy nhiên, bạn hỏi điều này 2 năm trước, và tôi làm chứng rằng rất nhiều đã thay đổi kể từ đó (với g + + ít nhất), devirtualization là đáng tin cậy hơn rất nhiều, ví dụ

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