2017-11-05 17 views
1

私は、行列乗算、行列逆行列、加算などの限られた一連の主要な線形代数演算を広範に使用(高頻度)するプロジェクトを持っています。これらの演算は、これらのさまざまなライブラリのさまざまな方法に対応するためにビジネスロジックコードを再コンパイルせずにベンチマークしたいと思っている非線形代数ライブラリです。ラッパークラスのC++効率的な実装

私はこれらの操作を残りのコードに対して標準化するために、これらのライブラリ全体の抽象としてラッパークラスを調整する最もスマートな方法を考え出すことに興味があります。私の現在のアプローチは、Curiously Recurring Template Patternと、C++ 11 gccが適切な状況下で仮想関数をインライン化するのに十分スマートであるという事実に依存しています。

これは、ビジネスロジックに利用できるようになりますラッパーインタフェースである:

template <class T> 
class ITensor { 

    virtual void initZeros(uint32_t dim1, uint32_t dim2) = 0; 
    virtual void initOnes(uint32_t dim1, uint32_t dim2) = 0; 
    virtual void initRand(uint32_t dim1, uint32_t dim2) = 0; 

    virtual T mult(T& t) = 0; 
    virtual T add(T& t) = 0; 
}; 

そしてここでは、例えば使用してそのインターフェイスの実装ですアルマジロ

template <typename precision> 
class Tensor : public ITensor<Tensor<precision> > 
{ 
    public: 

    Tensor(){} 
    Tensor(arma::Mat<precision> mat) : M(mat) { } 
    ~Tensor(){} 

    inline void initOnes(uint32_t dim1, uint32_t dim2) override final 
     { M = arma::ones<arma::Mat<precision> >(dim1,dim2); } 
    inline void initZeros(uint32_t dim1, uint32_t dim2) override final 
     { M = arma::zeros<arma::Mat<precision> >(dim1,dim2);} 
    inline void initRand(uint32_t dim1, uint32_t dim2) override final 
     { M = arma::randu<arma::Mat<precision> >(dim1,dim2);} 

    inline Tensor<precision> mult(Tensor<precision>& t1) override final 
    { 
     Tensor<precision> t(M * t1.M); 
     return t; 
    } 

    inline Tensor<precision> add(Tensor<precision>& t1) override final 
    { 
     Tensor<precision> t(M + t1.M); 
     return t; 
    } 

    arma::Mat<precision> M; 
}; 

質問:

  1. それは、このシナリオでCRTPとインライン化を使用する意味がありますか?
  2. これは、パフォーマンスの最適化に関して改善できますか?

答えで指摘したように、多態性の使用は基本クラスのテンプレート化のために少し奇妙です。

「ArmadilloTensor」のようなより具体的なものではなく、基本クラスの名前が「Tensor」であることがわかります(基本的に、Armadilloメソッドを使用するITensorメソッドを実装しています)。私の現在のデザインによれば、多形性の使用は何よりも形式主義の感覚によるものであるため、名前をそのまま残しました。計画は、プロジェクトコードがITensorで指定された機能を提供するTensorというクラスを認識することです。私がベンチマークしたい新しいライブラリごとに、新しいコンパイル単位に新しい "Tensor"クラスを書き、コンパイル結果を.aアーカイブにパッケージ化し、ベンチマークテストを行うときにビジネスロジックコードをリンクしますその図書館に対して異なる実装間を切り替えることで、どのTensor実装をリンクするかが決まります。ベースコードには、TensorメソッドがArmadilloやその他のもので実装されているかどうかは同じです。利点:すべてのライブラリ(すべて独立している)を知っているコードを避け、新しい実装を使用するためにベースコードにコンパイル時の変更を必要としません。だから、なぜ多型ですか?私の考えでは、ベンチマークに追加された新しいライブラリによって実装される必要がある関数を何らかの形で形式化したかっただけです。実際には、基本コードは関数パラメータでITセンサと連携しますが、メソッド本体自体のTensorsに潜在的にstatic_castします。

+0

ありがとう、名前が変更されました。 – nescience

+0

1については、頻繁に呼び出されるメソッドがインライン化されていると、コンテキストの変更が少なくなったため、パフォーマンスが向上するはずです。 – Rodrigo

答えて

1

私はここに何かを紛失しているか、詳細を十分に示していない可能性があります。

多型を使用します。その名前で定義されているように、それは異なる形(異なる振る舞い)を取っている同じ型です。したがって、ユーザーコードで受け入れられるインターフェイスがあり、そのインターフェイスのさまざまな実装を提供することができます。

しかし、あなたのケースでは、単一のインターフェイスの異なる実装を持っていません。ITensorテンプレートは異なるクラスを生成し、Tensorの各最終実装は異なるベースから派生しています。

は、ユーザーのコードは次のようなものです考えてみましょう:

template<typename T> 
void useTensor(ITensor<T>& tensor); 

、あなたのTensor実装を提供することができます。

template<typename T> 
void useTensor(T& tensor); 

CRTPと仮想呼び出しを使用していない場合とほぼ同じです。各ラッパーはいくつかの機能セットを実装する必要があります。この機能セットが明示的に定義されていないという問題があります。コンパイラはここで大きな助けになりますが、理想的ではありません。だから私たちは皆次の標準でConceptsを得ることを楽しみにしています。

+0

はい、あなたは正しいです、ここに欠けている情報が少しあります - 編集されたポストの注記を見てください。コンセプト、面白いものに向けて私を指してくれてありがとう。しかし、多型を別に使用すると(たとえITセンサを完全になくしたとしても)、コードを使用したいと思っている現在のデザインのパフォーマンスへの影響を考えることができますか? – nescience

+0

GCCがあなたの特定のケースであなたの仮想関数呼び出しをインライン化したというあなたの言葉を思い出しましたが、これはすべてのケースで同じことをするわけではありません。これを確認してください:http://www.cs.technion.ac.il/users/yechiel/c++-faq/inline-virtuals.html。したがって、インライン化ができないことが想定される場合は、インライン化できないだけでなく、仮想通話コストも意味するパフォーマンス上の影響があります。しかし、それは私の意見ではあまり問題ではないが、大きなものは、CRTPの不必要な合併症(それは一般的に非常に良い評判を持っていない)です。さらにメンテナンスのための複雑さ。 –

+0

ありがとう、私はこれに基づいて仮定しています:https://stackoverflow.com/questions/733737/are-inline-virtual-functions-really-a-non-sense。いずれにせよ、最も簡単なことは、ベンチマークを実行し、実行時のパフォーマンスを「ネイティブ」のArmadilloインターフェイスと比較することです。結果を投稿します! – nescience

関連する問題