2012-02-17 9 views
2

私は任意のテンソルで動作するはずのフィルタを持っています。私の場合は、フィルタがリスト1,2,3のテンソルで動作していれば十分です。リスト、マトリックス、3d-マトリックスまたはボリュームです。さらに、フィルタは、それぞれの可能な方向に適用することができます。リストの場合、これは1つのみであり、行列は2つの可能な方向(すなわちX方向およびY方向)に存在し、ボリュームに対しては3つの可能な方向が存在するからである。テンプレートを使用して汎用フィルタを実装する

詳細については、先に質問しましょう:フィルタのレイアウトは大丈夫ですか、後で苦労するかもしれない重要なものを忘れましたか?私はC++テンプレートには新しくないが、私は水中の魚のように感じるわけではない。このレイアウトをさらに圧縮することは可能ですか(ダミーのXDirectionクラスまたは短いType2Typeの周りには多分方法がありますか?

フィルタの基本的な手順は、すべてのテンソルランクとすべての方向について同じです。わずか数行のコードがありますが、機能はcallKernelです。オーバーロードされたoperator()を右のcallKernel関数を呼び出すには、以下のコードの中で唯一の興味深い部分です。テンプレートの部分的な特殊化はクラスメソッドでは機能しないので、テンプレート引数を実際のクラス型に変換し、これを仮引数としてcallKernelに渡すことができます。

次のコードは、ランク2までのレイアウトです。g++でコンパイルでき、試すことができます。

template <class DataType, int Rank> 
class Tensor { }; 

class XDirection; 
class YDirection; 

template <class TensorType, class Direction> 
struct Type2Type { 
    typedef TensorType TT; 
    typedef Direction D; 
}; 

template <class TensorType, class Direction> 
struct Filter { 
    Filter(const TensorType &t){} 
    TensorType operator()(){ 
    /* much code here */ 
    callKernel(Type2Type<TensorType,Direction>()); 
    /* more code */ 
    TensorType result; 
    return result; 
    } 
    void callKernel(Type2Type<Tensor<double,1>, XDirection>) {} 
    void callKernel(Type2Type<Tensor<double,2>, XDirection>) {} 
    void callKernel(Type2Type<Tensor<double,2>, YDirection>) {} 
}; 

int main(void) { 
    Tensor<double, 2> rank_two_tensor; 
    Filter<Tensor<double,2>,XDirection> f(rank_two_tensor); 
    f(); 
} 

私はいくつかの重要な事柄を追加してみましょう:何をここで見ることは、この構造を必要とインテルスレッディング・ビルディング・ブロックで使用起こっているので、フィルタロジックがoperator()であることが必要です。 callKernelがインライン化されていることは非常に重要です。私が知っているすべてから、これが当てはまるはずです。

ご協力いただきありがとうございます。

答えて

1

まず、テンプレートの最初の試行では悪くありません。

GCCの最新バージョンをお持ちの場合は、このように簡略化することができます。std::is_same<>を使用すると、条件付きで条件付きでコードを実行することができます。タイプが同じ場合はtrueを返します。それはまたあなたの意図をより明白にします。

#include <type_traits> 

template <class TensorType, class Direction> 
struct Filter { 
    Filter(const TensorType &t) { } 

    TensorType operator()(){ 
    /* much code here */ 
    callKernel(); 
    /* more code */ 
    TensorType result; 
    return result; 
    } 

    void callKernel() { 
     // Check which type is called at compile time (the if will be simplified by the compiler) 
     if (std::is_same<TensorType, Tensor<double, 2> >::value) { 
      if (std::is_same<Direction, XDirection>::value) { 
       // do stuff 
      } else { 
       ... 
      } 
     } else if (...) { 
      ... 
     } 
    } 
}; 

編集:あなたが希望する場合にも、コードがインライン化されていることを確認するためにop()に移動することができます。

+0

+1ありがとうございます。私は「Modern C++ Desing」から私の考えを得ました。 'is_same'呼び出しはコンパイル時に決定され、定数に変換されます。コンパイラーがif-elseステートメントを最適化する可能性はありますか?私は知っている、それは唯一の条件です..私は興味があります。 – halirutan

+0

まあ、正直言って私は通常私のコンパイラが行うと思う最適化をチェックしません。この特殊なケースでは、最近の十分なコンパイラを使用すると、それが起こることはかなり確信しています。あなたが確かめる唯一の方法は、逆アセンブリを見ることです...デバッグモードではなく、最適化を有効にしてコンパイルすることを忘れないでください。 –

+0

私は*「Modern C++ Design」は 'std :: is_same'より古いと思っていますが、私は両方の後にC++に来たので確認できません。 –

関連する問題