我正在读Tomas Arce的article。 本文讨论了使用模板提高矢量添加性能的方法。但有些部分我无法遵循。
作者说以下代码可以避免在评估时生成临时对象
vA = vB + vC + vD
,但是怎么样?我没有得到如何避免临时对象。是否有人可以解释内部机制,即在使用模板时如何避免临时对象。
template< class ta_a >
class vecarg
{
const ta_a& Argv;
public:
inline vecarg( const ta_a& A ) : Argv( A ) {}
inline const float Evaluate( const int i ) const
{ return Argv.Evaluate( i ); }
};
template<>
class vecarg< const float >
{
const ta_a& Argv;
public:
inline vecarg( const ta_a& A ) : Argv( A ) {}
inline const float Evaluate( const int i ) const { return Argv; }
};
template<>
class vecarg< const int >
{
const ta_a& Argv;
public:
inline vecarg( const ta_a& A ) : Argv( A ) {}
inline const float Evaluate( const int i ) const { return (float)Argv; }
};
template< class ta_a, class ta_b, class ta_eval >
class vecexp_2
{
const vecarg<ta_a> Arg1;
const vecarg<ta_b> Arg2;
public:
inline vecexp_2( const ta_a& A1, const ta_b& A2 )
: Arg1( A1 ), Arg2( A2 ) {}
inline const float Evaluate ( const int I ) const
{ return ta_eval::Evaluate( i, Arg1, Arg2 ); }
};
// Listing 5
P.S。在@Severin Pappadeux提供的第二个链接中,解释很容易理解。基本上,所有表达式模板都是这样的:通过重载运算符+
它甚至不执行添加,而是创建一个轻量级对象,其主要工作是对运算符每一侧的两个操作数进行两次引用{ {1}},并且在评估运算符+
时完成添加。通过重载操作符=
第二次(因为左侧是轻量级对象,右侧是+
),对轻量级对象的引用(包含两个先前对{{1}的引用可以创建}和vD
)和vB
,并在评估运算符vC
时再次添加。
答案 0 :(得分:2)
拿一块像底特律那样大小的盐。它已有14年历史,从那时起,优化器已经大大改善。简而言之,这个家伙正在使用模板制作一个复杂的方法网络,从而转换A = B + C + D:
// Taking liberties with pseudocode and notation for clarity. This is
// a very rough oversimplification
// Create a new, wasteful, vector to store a temporary result
vector tmp(C.x + D.x, C.y + D.y, C.z + D.z)
// Create another new, wasteful, vector to store a temporary result:
vector tmp2(B.x + tmp.x, B.y + tmp.y, B.z + tmp.z)
// Waste even more time copying the result.
A.x = tmp2.x; A.y = tmp2.y; A.z = tmp2.z;
// In reality, your optimized compiler isn't even remotely this stupid.
他正在使用模板预处理器来消除临时和最终副本的创建。他正试图达到执行这样的目的:
A.x = B.x + (C.x + D.x);
A.y = B.y + (C.y + D.y);
A.z = B.z + (C.z + D.z);
请记住,如果你把这样的东西放在其他工程师必须阅读的生产代码中,你就会有更好的理由。就像在,你将必须证明使用这种乱码可以产生关键任务的性能提升。为什么?因为维持这种精神错乱的代价是不可忽视的。在使用此类内容之前,请先获取性能数据。
答案 1 :(得分:0)
技术被称为“表达模板”,其发明者Todd Veldhuizen有几篇论文, 从
开始http://ubietylab.net/ubigraph/content/Papers/pdf/ExpressionTemplates.pdf
和
http://www.drdobbs.com/cpp/expression-templates/184401656
最后是托德报告
答案 2 :(得分:0)
整个概念依赖于存储对本机类型的引用,或者评估折叠为本机类型的表达式。
有一些临时对象参与其中,但它们存储的所有内容都是对源和目标数据的引用,这些数据会在某些时候得到解决。在没有优化的情况下进行编译可能确实会分配空间,但如果启用了优化,优化器会注意到没有理由这样做。
也就是说,如果为使用寄存器的CPU编译它。基于堆栈的机器可能表现不同,因为操作仍然需要推送和弹出它们的操作数。