C++ 已知矩阵的模板矩阵表达式

C++ 已知矩阵的模板矩阵表达式,c++,templates,matrix,C++,Templates,Matrix,这是一个思考练习,不是一个特别的问题,但我想听听你的意见。假设我有一些使用模板(Eigen、ublas等)的矩阵表达式DSL 现在假设我有一些常数矩阵,例如: Matrix2 sigma1 = {{0,1}, {1,0}}; Matrix2 sigma2 = {{0,i}, {-i,0}}; ... etc 。。。我有一些涉及运行时值的矩阵运算: a*sigma1 + b*sigma2; // a,b runtime 您有什么想法来实现常量矩阵,以便编译器能够最大限度地优化表达式?特别是,如

这是一个思考练习,不是一个特别的问题,但我想听听你的意见。假设我有一些使用模板(Eigen、ublas等)的矩阵表达式DSL

现在假设我有一些常数矩阵,例如:

Matrix2 sigma1 = {{0,1}, {1,0}};
Matrix2 sigma2 = {{0,i}, {-i,0}};
... etc
。。。我有一些涉及运行时值的矩阵运算:

a*sigma1 + b*sigma2; // a,b runtime

您有什么想法来实现常量矩阵,以便编译器能够最大限度地优化表达式?特别是,如何将
(I,j)
运算符解析为常数?

根据我对问题空间的理解:给定a,我们希望确定最小变换,使得数据上的某些运算符(例如,
(I,j)
)导致查找常数,而不是计算数学公式(例如,
a*sigma1+b*sigma2

让我们在这里探讨一些可能性:

  • 直接执行数学运算

    如果编译器没有显式优化,如果直接执行指令会发生什么

    答案是这要视情况而定。但是,在大多数处理器上,您的代码执行将落在上面,在那里您的汇编和分支执行将被优化到您核心的最佳能力。该过程的精髓是,但我们假设您希望超越这些能力,并直接在c语言中解决操作的稳定性问题颂歌

  • 使用

    一阶优化是使用a绑定和捕获可能的输入和输出空间。虽然这将有效地解决您的输入范围,仅将其限制在您想要的输入和输出集,但它对性能没有任何影响。因此,我们必须继续

  • 二阶优化是直接执行值空间的字符串或宏扩展。尽管如此,如果需要操作,也可以由编译器直接执行。(另请参见:)

  • 模型的人工求导和堆栈界可满足性
    (例如,使用查找表)

    最后,我们的三阶优化将直接绑定你的空间。这需要你有一个定义良好的有界输入和输出空间来有效地工作。如果这个关系不能被确定或没有边界,并且应该考虑保持当前的实现,如果一个更好的一个不知道存在。

在这些优化技术中,考虑到您所描述的问题边界,最适用于后两种。因为大多数操作(如矩阵平移、旋转和缩放操作)本质上是确定性的,因此您确实可以有效地优化和约束空间


对于一个更理论的答案,我建议咨询,和。这两个都有很多很多线程致力于整个方程类的闭式形式和证明。

好吧,这很可怕,但与我在原始帖子上的评论有关

使用此结构应该可以定义所需的相关操作,但编写所有适当的专门化需要大量的工作。您也可能希望交换行/列

在最后定义矩阵当然不像您原来的帖子中那样优雅,但这可能会有所改进,特别是在C++11中使用“auto”时

//-----------------------------------------------------------------------------
struct Unused {};

struct Imaginary {
    Imaginary() {}
    Imaginary(Unused const& unused) {}
};
struct MinusImaginary {
    MinusImaginary() {}
    MinusImaginary(Unused const& unused) {}
};

//-----------------------------------------------------------------------------
template <int I, int F = 0>
struct Fixed {
    Fixed() {}
    Fixed(Unused const& unused) {}
};

//-----------------------------------------------------------------------------
struct Float
{
    Float(float value) : value_(value) {}
    const float value_;
};

//-----------------------------------------------------------------------------
template <typename COL0, typename COL1>
struct Vector2
{
    typedef COL0 col0_t;
    typedef COL1 col1_t;

    template <typename T0, typename T1>
    Vector2(T0 const& t0, T1 const& t1)
        : col0_(t0)
        , col1_(t1)
    {}

    COL0 col0_;
    COL1 col1_;
};

//-----------------------------------------------------------------------------
template <typename ROW0, typename ROW1>
struct Matrix2
{
    typedef ROW0 row0_t;
    typedef ROW1 row1_t;

    Matrix2()
        : row0_(Unused(), Unused())
        , row1_(Unused(), Unused())
    {
    }
    template <typename M00, typename M01, typename M10, typename M11>
    Matrix2(M00 const& m00, M01 const& m01, M10 const& m10, M11 const& m11)
        : row0_(m00, m01)
        , row1_(m10, m11)
    {
    }

    ROW0 row0_;
    ROW1 row1_;
};

//-----------------------------------------------------------------------------
Matrix2<
    Vector2< Fixed<0>, Fixed<1> >,
    Vector2< Fixed<1>, Fixed<0> > 
> sigma1;

const float f = 0.1f;

//-----------------------------------------------------------------------------
Matrix2<
    Vector2< Fixed<0>, Imaginary >,
    Vector2< MinusImaginary, Fixed<0> > 
> sigma2;

//-----------------------------------------------------------------------------
Matrix2<
    Vector2< Fixed<0>, Float >,
    Vector2< Float, Fixed<0> > 
> m3(Unused(), 0.2f,
     0.8f, Unused());


// EDIT: Nicer initialization syntax in c++11

//-----------------------------------------------------------------------------
template <typename M00, typename M01, typename M10, typename M11>
Matrix2< Vector2<M00, M01>, Vector2<M10, M11> >
MakeMatrix(M00 const& m00, M01 const& m01, M10 const& m10, M11 const& m11)
{
    return Matrix2< Vector2<M00, M01>, Vector2<M10, M11> >(m00,m01,m10,m11);
}

auto m4 = MakeMatrix(Fixed<0>(),  Float(0.2f), 
                     Float(0.8f), Fixed<0>()  );
//-----------------------------------------------------------------------------
结构未使用{};
想象结构{
虚数(){}
虚(未使用的常量和未使用的){}
};
虚数结构{
极小值({}
极小值(未使用的常量和未使用的){}
};
//-----------------------------------------------------------------------------
模板
结构固定{
已修复(){}
固定(未使用的常量和未使用的){}
};
//-----------------------------------------------------------------------------
结构浮动
{
浮动(浮动值):值(值{}
常量浮点值;
};
//-----------------------------------------------------------------------------
模板
结构向量2
{
typedef COL0 COL0\t;
typedef COL1 COL1_t;
模板
矢量2(T0常数和T0,T1常数和T1)
:col0(t0)
,col1(t1)
{}
COL0-COL0;
COL1 COL1_2;;
};
//-----------------------------------------------------------------------------
模板
结构矩阵2
{
typedef第0行第0行;
类型定义第1行第1行;
Matrix2()
:第0行(未使用的(),未使用的())
,第1行(未使用的(),未使用的())
{
}
模板
矩阵2(M00常数和M00、M01常数和M01、M10常数和M10、M11常数和M11)
:第0行(m00、m01)
,第1行(m10,m11)
{
}
第0行第0行;
第1行第1行;
};
//-----------------------------------------------------------------------------
Matrix2<
向量2,
向量2<固定,固定>
>sigma1;
常数浮点f=0.1f;
//-----------------------------------------------------------------------------
Matrix2<
向量2<固定的,假想的>,
向量2<虚拟的,固定的>
>sigma2;
//-----------------------------------------------------------------------------
Matrix2<
向量2<固定,浮动>,
矢量2<浮动,固定>
>m3(未使用的(),0.2f,
0.8f,未使用();
//编辑:c++11中更好的初始化语法
//-----------------------------------------------------------------------------
模板
矩阵2<向量2,向量2>
MakeMatrix(M00常量和M00、M01常量和M01、M10常量和M10、M11常量和M11)
{
返回矩阵2(m00,m01,m10,m11);
}
auto m4=生成矩阵(固定(),浮动(0.2f),
浮动(0.8f),固定();

为了使其成为现实场景,变换矩阵正是如此,因此,例如,通过某个给定角度的旋转或通过某个给定因子的缩放可以进行优化。正如@TC1所指出的。我认为