2012-02-17 68 views
2

我有一个过滤器应该在任意张量上工作。对于我的情况,当滤波器分别在列表,矩阵和3d矩阵或体积的1,2和3张张上工作时就足够了。另外,可以在每个可能的方向上应用滤波器。对于一个列表来说,这只是一个,对于矩阵存在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谢谢,这是短。我从“现代C++设计”中获得了我的想法。 'is_same'调用在编译时确定并转换为常量,对吧?编译器是否有机会优化if-else语句?我知道,这只是一个条件。我只是好奇。 – halirutan 2012-02-17 12:14:36

+0

嗯,说实话我通常不会检查我认为我的编译器会做的优化。在这种特殊情况下,我相当确信如果您使用了最新的编译器,就会发生这种情况。要确定的唯一方法是查看反汇编...不要忘记在启用优化的情况下进行编译,而不是在调试模式下进行编译。 – 2012-02-18 12:52:04

+0

我认为*“现代C++设计”比'std :: is_same'早,但是我在两者之后来到C++,所以我无法确认;)。 – 2012-02-18 12:52:32

相关问题