2012-08-10 44 views
8

Tôi đang cố gắng đo hiệu suất khác biệt giữa việc sử dụng Boost.Variant và sử dụng giao diện ảo. Ví dụ, giả sử tôi muốn tăng các loại khác nhau của các số thống nhất, bằng cách sử dụng Boost.Variant tôi sẽ sử dụng một tăng :: biến thể trên int và float và một khách truy cập tĩnh mà tăng mỗi một trong số họ. Sử dụng các giao diện lớp Tôi sẽ sử dụng một số lớp ảo thuần túy và các lớp number_int và number_float xuất phát từ nó và thực hiện một phương thức "increment".

Từ thử nghiệm của tôi, việc sử dụng giao diện nhanh hơn nhiều so với việc sử dụng Boost.Variant. Tôi chạy mã ở phía dưới và nhận được những kết quả này:
ảo: 00: 00: 00.001028
Ngôn ngữ địa phương: 00: 00: 00,012081
Boost.Variant Vs Hiệu suất Giao diện Ảo

Tại sao bạn cho rằng sự khác biệt này là gì? Tôi nghĩ Boost.Variant sẽ nhanh hơn rất nhiều.

** Lưu ý: Thông thường Boost.Variant sử dụng phân bổ heap để đảm bảo rằng biến thể sẽ luôn không trống. Nhưng tôi đọc trên tài liệu Boost.Variant rằng nếu boost :: has_nothrow_copy là true thì nó không sử dụng phân bổ heap mà nên làm cho mọi thứ nhanh hơn đáng kể. Đối với tăng cường int và float :: has_nothrow_copy là true.

Đây là mã của tôi để đo hai cách tiếp cận với nhau.

#include <iostream> 

#include <boost/variant/variant.hpp> 
#include <boost/variant/static_visitor.hpp> 
#include <boost/variant/apply_visitor.hpp> 

#include <boost/date_time/posix_time/ptime.hpp> 
#include <boost/date_time/posix_time/posix_time_types.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 

#include <boost/format.hpp> 

const int iterations_count = 100000; 

// a visitor that increments a variant by N 
template <int N> 
struct add : boost::static_visitor<> { 
    template <typename T>  
    void operator() (T& t) const { 
     t += N; 
    } 
}; 

// a number interface 
struct number {   
    virtual void increment() = 0; 
}; 

// number interface implementation for all types 
template <typename T> 
struct number_ : number { 
    number_(T t = 0) : t(t) {} 
    virtual void increment() { 
     t += 1; 
    } 
    T t; 
}; 

void use_virtual() { 
    number_<int> num_int; 
    number* num = &num_int; 

    for (int i = 0; i < iterations_count; i++) { 
     num->increment(); 
    } 
} 

void use_variant() { 
    typedef boost::variant<int, float, double> number; 
    number num = 0; 

    for (int i = 0; i < iterations_count; i++) { 
     boost::apply_visitor(add<1>(), num); 
    } 
} 

int main() { 
    using namespace boost::posix_time; 

    ptime start, end; 
    time_duration d1, d2; 

    // virtual 
    start = microsec_clock::universal_time(); 
    use_virtual(); 
    end = microsec_clock::universal_time(); 

    // store result 
    d1 = end - start; 

    // variant 
    start = microsec_clock::universal_time(); 
    use_variant(); 
    end = microsec_clock::universal_time(); 

    // store result 
    d2 = end - start; 

    // output 
    std::cout << 
     boost::format(
      "Virtual: %1%\n" 
      "Variant: %2%\n" 
     ) % d1 % d2; 
} 

Trả lời

14

Đối với những người quan tâm, sau khi tôi đã hơi thất vọng, tôi đã thông qua tùy chọn -O2 để trình biên dịch và đẩy mạnh :: biến thể là cách nhanh hơn so với một cuộc gọi ảo.
Cảm ơn

+0

Cám ơn đăng theo dõi, tôi đã quan tâm! –

+0

Kết quả của bạn và trình biên dịch gì? Sử dụng Boost 1.52 và Mingw 4.7 Tôi nhận được biến thể chậm hơn khoảng 8 lần trong chế độ phát hành. Kỳ lạ đủ '-O2' là hơi nhanh hơn' -O3';/ – AbstractDissonance

+0

Tôi đang sử dụng g ++ 4.7 và tôi không chắc chắn phiên bản Boost nhưng nó có thể là 1.5x. Tôi đã thông qua -O2 cho trình biên dịch và kết quả của tôi là: Ảo: 00: 00: 00.018806 Biến thể: 00: 00: 00.000001 Hầu hết thời gian tôi sẽ nhận được 00:00:00 trên biến thể vì vậy tôi đặt iterations_count thành 10000000 Tôi đang chạy thử nghiệm này trên CPU Intel Core i7 2.8Ghz. –

4

Điều này rõ ràng là -O2 làm giảm thời gian biến thể, vì toàn bộ vòng lặp đó được tối ưu hóa. Thay đổi việc thực hiện để trả lại kết quả tích lũy cho người gọi, vì vậy mà tôi ưu hoa sẽ không loại bỏ các vòng lặp, và bạn sẽ nhận được sự khác biệt thực:

Output:
ảo: 00: 00: 00,000120 = 10000000
Ngôn ngữ địa phương: 00: 00: 00,013483 = 10000000

#include <iostream> 

#include <boost/variant/variant.hpp> 
#include <boost/variant/static_visitor.hpp> 
#include <boost/variant/apply_visitor.hpp> 

#include <boost/date_time/posix_time/ptime.hpp> 
#include <boost/date_time/posix_time/posix_time_types.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 

#include <boost/format.hpp> 

const int iterations_count = 100000000; 

// a visitor that increments a variant by N 
template <int N> 
struct add : boost::static_visitor<> { 
    template <typename T> 
    void operator() (T& t) const { 
     t += N; 
    } 
}; 

// a visitor that increments a variant by N 
template <typename T, typename V> 
T get(const V& v) { 
    struct getter : boost::static_visitor<T> { 
     T operator() (T t) const { return t; } 
    }; 
    return boost::apply_visitor(getter(), v); 
} 

// a number interface 
struct number { 
    virtual void increment() = 0; 
}; 

// number interface implementation for all types 
template <typename T> 
struct number_ : number { 
    number_(T t = 0) : t(t) {} 
    virtual void increment() { t += 1; } 
    T t; 
}; 

int use_virtual() { 
    number_<int> num_int; 
    number* num = &num_int; 

    for (int i = 0; i < iterations_count; i++) { 
     num->increment(); 
    } 

    return num_int.t; 
} 

int use_variant() { 
    typedef boost::variant<int, float, double> number; 
    number num = 0; 

    for (int i = 0; i < iterations_count; i++) { 
     boost::apply_visitor(add<1>(), num); 
    } 

    return get<int>(num); 
} 
int main() { 
    using namespace boost::posix_time; 

    ptime start, end; 
    time_duration d1, d2; 

    // virtual 
    start = microsec_clock::universal_time(); 
    int i1 = use_virtual(); 
    end = microsec_clock::universal_time(); 

    // store result 
    d1 = end - start; 

    // variant 
    start = microsec_clock::universal_time(); 
    int i2 = use_variant(); 
    end = microsec_clock::universal_time(); 

    // store result 
    d2 = end - start; 

    // output 
    std::cout << 
     boost::format(
      "Virtual: %1% = %2%\n" 
      "Variant: %3% = %4%\n" 
     ) % d1 % i1 % d2 % i2; 
} 
+3

Điều đó vẫn không hiển thị ảo là 2 đơn vị cường độ nhanh hơn? –

+0

Bạn có chắc trình biên dịch không phải là ảo hóa không? – Brahim

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