私はBoost.Variantを使用して仮想インターフェイスを使用するパフォーマンスの違いを測定しようとしています。たとえば、Boost.Variantを使用して異なるタイプの数値を一様に増やしたいとします。私は、boost :: variantをintおよびfloatに使用し、静的ビジターはそれぞれを増分します。クラスインタフェースを使用して、純粋な仮想クラス番号とそれから派生し、 "インクリメント"メソッドを実装するnumber_intクラスとnumber_floatクラスを使用します。
私のテストでは、インターフェイスを使用する方がBoost.Variantを使用するよりもはるかに高速です。 は私が一番下にあるコードを実行し、これらの結果を受けた:
仮想:00:00:00.001028
バリアント:00:00:00.012081
Boost.Variantと仮想インターフェイスのパフォーマンス
あなたはこの差があると思いますなぜ?私はBoost.Variantがもっと速くなると思った。
**注:通常Boost.Variantは、バリアントが常に空でないことを保証するためにヒープ割り当てを使用します。しかし、boost :: has_nothrow_copyが真である場合、ヒープ割り当てを使用しないため、作業が大幅に高速化されるはずです。 intとfloatの場合、boost :: has_nothrow_copyはtrueです。
ここでは、2つのアプローチを相互に測定するためのコードを示します。興味のある方のため
#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;
}
おかげで、私が興味を持っていました! –
あなたの結果とコンパイラは何ですか? Boost 1.52とMingw 4.7を使用すると、リリースモードで約8倍の遅れが発生します。奇妙なことに、 '-O2'は' -O3'より少し速いです。/ – AbstractDissonance
g ++ 4.7を使っていますが、Boostのバージョンは分かりませんが、おそらく1.5xです。私はコンパイラに-O2を渡して、結果は次のようになりました: バーチャル:00:00:00.018806 バリアント:00:00:00.000001 ほとんどの場合、私は0000:00:00を変種に渡しますので、iterations_countを10000000に設定します 私はこのテストを2.8Ghz Intel Core i7 CPUで実行しています。 –