13

Hãy nói rằng tôi có metafunction sau:Tối ưu hóa hiệu suất thời gian biên dịch bởi bộ nhớ đệm metafunctions

template <typename T> 
struct make_pair { 
    using type = std::pair< 
     typename std::remove_reference<T>::type, 
     typename std::remove_reference<T>::type 
    >; 
}; 

Nó sẽ cải thiện tốc độ biên soạn để làm điều này (hay cái gì khác) để thay thế?

template <typename T> 
struct make_pair { 
    using without_reference = typename std::remove_reference<T>::type; 
    using type = std::pair<without_reference, without_reference>; 
}; 

tôi thấy hai khả năng:

  1. Trình biên dịch đã làm một số công việc mỗi khi nó thấy typename std::remove_reference<T>::type. Sử dụng một bí danh trung gian có một số loại hành vi "bộ nhớ đệm", cho phép trình biên dịch thực hiện một số công việc chỉ một lần.

  2. Hiệu suất thời gian biên dịch được đo lường về số lượng bản mẫu tức thời mà trình biên dịch phải làm. Bởi vì std::remove_reference<T>::type đề cập đến cùng một loại như std::remove_reference<T>::type, chỉ có một bản mẫu được yêu cầu trong cả hai trường hợp, vì vậy cả hai triển khai đều tương đương với hiệu suất thời gian biên dịch WRT.

Tôi nghĩ B là đúng, nhưng tôi muốn chắc chắn. Nếu câu trả lời hóa ra là trình biên dịch cụ thể, tôi chủ yếu sẽ quan tâm đến việc biết câu trả lời cho Clang và GCC.

Sửa:

tôi làm chuẩn biên soạn của một chương trình thử nghiệm để có một số dữ liệu để làm việc với. Các chương trình thử nghiệm điều gì đó như thế:

template <typename ...> struct result;  

template <typename T> 
struct with_cache { 
    using without_reference = typename std::remove_reference<T>::type; 
    using type = result<without_reference, ..., without_reference>; 
}; 

template <typename T> 
struct without_cache { 
    using type = result< 
     typename std::remove_reference<T>::type, 
     ..., 
     typename std::remove_reference<T>::type 
    >; 
{ }; 

using Result = with[out]_cache<int>::type; 

Đây là những lần trung bình cho 10 sưu tập của chương trình, với 10 000 thông số mẫu trong result<>.

   ------------------------- 
       | g++ 4.8 | clang++ 3.2 | 
----------------------------------------- 
| with cache | 0.1628s | 0.3036s  | 
----------------------------------------- 
| without cache | 0.1573s | 0.3785s  | 
----------------------------------------- 

Chương trình thử nghiệm được tạo bởi tập lệnh có sẵn here.

+4

Tôi nghĩ rằng không có số lượng đầu cơ có thể thay thế các phép đo thực tế. Xin vui lòng gửi một số số liệu thời gian sau đó chúng ta có thể tạo ra một lý thuyết tốt đẹp để giải thích chúng. –

+0

Tôi đã thấy một cuộc trò chuyện trên tiếng kêu vang rằng họ tạo ra hashtables cho các bản mẫu ngay lập tức thay vì các danh sách được liên kết. Tôi không biết họ đang so sánh mình với ai. –

+0

Trình biên dịch 'mẫu' không thực hiện việc ghi nhớ sẽ rất chậm. – Yakk

Trả lời

2

Tôi không thể nói điều này đúng với tất cả các trình biên dịch nhưng GCC, và hầu như tất cả các trình biên dịch chính khác, sẽ sử dụng tính năng ghi nhớ. Nếu bạn nghĩ về nó, nó gần như phải.

Xét đoạn mã sau

&f<X, Y>::some_value == &f<X, Y>::some_value 

này là cần thiết đến mức khó tin, vì vậy trình biên dịch phải chắc chắn rằng nó không trùng lặp với các định nghĩa của các phương pháp và các thành viên tĩnh. Bây giờ có thể có những cách khác để làm điều này, nhưng điều này chỉ la hét ghi nhớ cho tôi; Tôi không thấy cách nào khác để thực hiện điều này ngay cả (được cấp, tôi đã nghĩ về nó rất khó)

Khi tôi sử dụng TMP, tôi mong đợi việc ghi nhớ xảy ra. Nó sẽ là một nỗi đau thực sự nếu nó không, quá chậm. Cách duy nhất tôi đã thấy sự khác biệt lớn trong hiệu suất thời gian biên dịch là hoặc là a) bằng cách sử dụng trình biên dịch nhanh hơn như Clang (nhanh gấp 3 lần so với GCC) và chọn các thuật toán khác nhau. Các yếu tố liên tục nhỏ dường như đối với tôi ít quan trọng hơn trong TMP so với C hoặc C++ trong kinh nghiệm của tôi. Chọn thuật toán đúng, cố gắng không làm việc không cần thiết, cố gắng giữ số lượng instantiations xuống, và sử dụng trình biên dịch tốt (MSVC++ là thực sự chậm và xa C++ 11 tuân thủ nhưng GCC và Clang khá tốt); đây là tất cả những gì bạn có thể làm.

Ngoài ra, bạn luôn phải hy sinh thời gian biên dịch để có mã tốt hơn. Tối ưu hóa thời gian biên dịch sớm là cách xấu xa hơn so với tối ưu hóa đồng bằng sớm. Có thể có một ngoại lệ đối với điều này nếu vì một lý do nào đó hiệu suất trở nên nghiêm trọng cấm phát triển; Tôi không bao giờ nghe nói về một trường hợp như vậy tuy nhiên.

+1

Câu trả lời này không phải là xấu, nhưng nó không thực sự là những gì tôi đang tìm kiếm. Tôi đang tìm kiếm một cái gì đó chắc chắn hơn như một xác nhận từ một nhà phát triển GCC hoặc Clang. Ngoài ra, lý do tại sao tôi đã đặt câu hỏi này là bởi vì tôi đã làm việc trên các thư viện lập trình meta và tối ưu hóa thời gian biên dịch là rất quan trọng. –

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