5

テンプレートを使用できる場所でboost.any(RTTIなし)クラスを使用すると、プログラムの速度が低下するのではないかと思いました。boost anyは実際にはテンプレートクラスのラッパーであるため、最新のコンパイラ最適化では同じ効果が得られると言えますね。

tpl_vs_any.hpp

#include <iostream>
#include <vector>

using namespace std;

template<class T> class tpl
{
    T content;
public:
    tpl(const T& value) : content(value) {}
    operator T() const
    {
        return content;
    }
};

class any
{
public:

    any() : content(0) {}

    any(const any& other) : content(other.content -> clone()) {}

    template<class T> any(const T& value) : content(new holder<T>(value))
    {
    }

    ~any() 
    {
        delete content;
    }

    class placeholder
    {
    public:
        placeholder() {}
        virtual placeholder* clone() const = 0;
    };

    template<class T> class holder : public placeholder
    {
    public:
        T content;

        holder(const T& value) : content(value) {}
        ~holder() {}

        placeholder* clone() const
        {
            return new holder<T>(content);
        }
    };

    template<class T> operator T () const
    {
        return dynamic_cast<holder<T>*>(content)->content;
    }

    placeholder* content;
};

template<class T> void test()
{
    for (int i = 0; i < 10000; ++i)
    {
        vector<T> a;
        a.push_back(23.23);
        a.push_back(3.14);

        double x = (double)a[0];
    }
}

したがって、次のように言うのは正しいでしょうか。

test<any>();

正確に同じくらい速いです:

test<tpl<double>>();

あなたが知っていると仮定すると、コンパイラが2番目の例で行うように、それboost::anyはこの状況でdoubleとしてのみ使用されますか?(どのクラスにもRTTIはありません)。

私はこの論文の賛否両論についてもっと疑問に思っています。

また、これらの方法に違いがある特定の状況はありますか?

編集: パフォーマンステスト2:

  • 例1:1,966.57ミリ秒
  • 例2:1,320.37ミリ秒

比較的大きな違いがあるようです。

編集2:doubleプライマリデータ型をクラス と比較することは公平ではなかったので、any私は新しいテストを行いました:

#include "tpl_vs_any.hpp"

int main()
{
    test<any>();
    return 0;
}

速度:1,794.54ミリ秒

#include "tpl_vs_any.hpp"

int main()
{
    test<tpl<double>>();
    return 0;
}

速度:1,715.57ミリ秒

ほぼ同じベンチマークで、複数回テストしました。

4

2 に答える 2

2

boost::anyは、オブジェクトへのポインターを内部的に保持し、それを で割り当てnewます。std::vectorたとえば、ベクターよりも大幅に高速化することの 1 つは、std::listすべてのオブジェクトを 1 回の割り当てで連続したストレージに保持することです。これは、メモリ割り当てのオーバーヘッドが明らかに削減されることを除けば、はるかにキャッシュに適しています。

割り当てに RTTI を追加する詳細もありますが、これは一般的に些細なオーバーヘッドですが、非常に小さな型の場合double、ストレージのオーバーヘッドが大幅に増加します。

boost::any標準の一部ではありません。これは、特定のテンプレートの特定の実装です。したがって、ベンチマークするだけでもかまいません。他の競合する「標準実装」はあまりありません。

于 2012-12-15T01:15:39.673 に答える
2

したがって、次のように言うのは正しいでしょうか。

...

次のように正確に高速です。

...

コンパイラが 2 番目の例で行うように、boost::any はこの状況では double としてのみ使用されることを知っていると仮定しますか?

いいえ。現在のコンパイラは、そのようなレベルのイントロスペクションにはほど遠いです。boost::any遅くなります。

もちろん、コードを実行して自分で調べることもできます。

于 2012-12-15T00:58:15.923 に答える