blob: d2a704f132a3b580d85db51a4083d7e15535a985 [file] [log] [blame]
Brian Silverman72890c22015-09-19 14:37:37 -04001namespace Eigen {
2
3/** \page TopicLazyEvaluation Lazy Evaluation and Aliasing
4
Austin Schuhc55b0172022-02-20 17:52:35 -08005Executive summary: %Eigen has intelligent compile-time mechanisms to enable lazy evaluation and removing temporaries where appropriate.
Brian Silverman72890c22015-09-19 14:37:37 -04006It will handle aliasing automatically in most cases, for example with matrix products. The automatic behavior can be overridden
7manually by using the MatrixBase::eval() and MatrixBase::noalias() methods.
8
9When you write a line of code involving a complex expression such as
10
Austin Schuhc55b0172022-02-20 17:52:35 -080011\code mat1 = mat2 + mat3 * (mat4 + mat5);
12\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040013
Austin Schuhc55b0172022-02-20 17:52:35 -080014%Eigen determines automatically, for each sub-expression, whether to evaluate it into a temporary variable. Indeed, in certain cases it is better to evaluate a sub-expression into a temporary variable, while in other cases it is better to avoid that.
Brian Silverman72890c22015-09-19 14:37:37 -040015
16A traditional math library without expression templates always evaluates all sub-expressions into temporaries. So with this code,
17
Austin Schuhc55b0172022-02-20 17:52:35 -080018\code vec1 = vec2 + vec3;
19\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040020
21a traditional library would evaluate \c vec2 + vec3 into a temporary \c vec4 and then copy \c vec4 into \c vec1. This is of course inefficient: the arrays are traversed twice, so there are a lot of useless load/store operations.
22
Austin Schuhc55b0172022-02-20 17:52:35 -080023Expression-templates-based libraries can avoid evaluating sub-expressions into temporaries, which in many cases results in large speed improvements.
24This is called <i>lazy evaluation</i> as an expression is getting evaluated as late as possible.
25In %Eigen <b>all expressions are lazy-evaluated</b>.
26More precisely, an expression starts to be evaluated once it is assigned to a matrix.
27Until then nothing happens beyond constructing the abstract expression tree.
28In contrast to most other expression-templates-based libraries, however, <b>%Eigen might choose to evaluate some sub-expressions into temporaries</b>.
29There are two reasons for that: first, pure lazy evaluation is not always a good choice for performance; second, pure lazy evaluation can be very dangerous, for example with matrix products: doing <tt>mat = mat*mat</tt> gives a wrong result if the matrix product is directly evaluated within the destination matrix, because of the way matrix product works.
Brian Silverman72890c22015-09-19 14:37:37 -040030
Austin Schuhc55b0172022-02-20 17:52:35 -080031For these reasons, %Eigen has intelligent compile-time mechanisms to determine automatically which sub-expression should be evaluated into a temporary variable.
Brian Silverman72890c22015-09-19 14:37:37 -040032
33So in the basic example,
34
Austin Schuhc55b0172022-02-20 17:52:35 -080035\code mat1 = mat2 + mat3;
36\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040037
Austin Schuhc55b0172022-02-20 17:52:35 -080038%Eigen chooses not to introduce any temporary. Thus the arrays are traversed only once, producing optimized code.
39If you really want to force immediate evaluation, use \link MatrixBase::eval() eval()\endlink:
Brian Silverman72890c22015-09-19 14:37:37 -040040
Austin Schuhc55b0172022-02-20 17:52:35 -080041\code mat1 = (mat2 + mat3).eval();
42\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040043
44Here is now a more involved example:
45
Austin Schuhc55b0172022-02-20 17:52:35 -080046\code mat1 = -mat2 + mat3 + 5 * mat4;
47\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040048
Austin Schuhc55b0172022-02-20 17:52:35 -080049Here again %Eigen won't introduce any temporary, thus producing a single <b>fused</b> evaluation loop, which is clearly the correct choice.
Brian Silverman72890c22015-09-19 14:37:37 -040050
Austin Schuhc55b0172022-02-20 17:52:35 -080051\section TopicLazyEvaluationWhichExpr Which sub-expressions are evaluated into temporaries?
Brian Silverman72890c22015-09-19 14:37:37 -040052
Austin Schuhc55b0172022-02-20 17:52:35 -080053The default evaluation strategy is to fuse the operations in a single loop, and %Eigen will choose it except in a few circumstances.
Brian Silverman72890c22015-09-19 14:37:37 -040054
Austin Schuhc55b0172022-02-20 17:52:35 -080055<b>The first circumstance</b> in which %Eigen chooses to evaluate a sub-expression is when it sees an assignment <tt>a = b;</tt> and the expression \c b has the evaluate-before-assigning \link flags flag\endlink.
56The most important example of such an expression is the \link Product matrix product expression\endlink. For example, when you do
57
58\code mat = mat * mat;
59\endcode
60
61%Eigen will evaluate <tt>mat * mat</tt> into a temporary matrix, and then copies it into the original \c mat.
62This guarantees a correct result as we saw above that lazy evaluation gives wrong results with matrix products.
63It also doesn't cost much, as the cost of the matrix product itself is much higher.
64Note that this temporary is introduced at evaluation time only, that is, within operator= in this example.
65The expression <tt>mat * mat</tt> still return a abstract product type.
Brian Silverman72890c22015-09-19 14:37:37 -040066
67What if you know that the result does no alias the operand of the product and want to force lazy evaluation? Then use \link MatrixBase::noalias() .noalias()\endlink instead. Here is an example:
68
Austin Schuhc55b0172022-02-20 17:52:35 -080069\code mat1.noalias() = mat2 * mat2;
70\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040071
Austin Schuhc55b0172022-02-20 17:52:35 -080072Here, since we know that mat2 is not the same matrix as mat1, we know that lazy evaluation is not dangerous, so we may force lazy evaluation. Concretely, the effect of noalias() here is to bypass the evaluate-before-assigning \link flags flag\endlink.
Brian Silverman72890c22015-09-19 14:37:37 -040073
Austin Schuhc55b0172022-02-20 17:52:35 -080074<b>The second circumstance</b> in which %Eigen chooses to evaluate a sub-expression, is when it sees a nested expression such as <tt>a + b</tt> where \c b is already an expression having the evaluate-before-nesting \link flags flag\endlink.
75Again, the most important example of such an expression is the \link Product matrix product expression\endlink.
76For example, when you do
Brian Silverman72890c22015-09-19 14:37:37 -040077
Austin Schuhc55b0172022-02-20 17:52:35 -080078\code mat1 = mat2 * mat3 + mat4 * mat5;
79\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040080
Austin Schuhc55b0172022-02-20 17:52:35 -080081the products <tt>mat2 * mat3</tt> and <tt>mat4 * mat5</tt> gets evaluated separately into temporary matrices before being summed up in <tt>mat1</tt>.
82Indeed, to be efficient matrix products need to be evaluated within a destination matrix at hand, and not as simple "dot products".
83For small matrices, however, you might want to enforce a "dot-product" based lazy evaluation with lazyProduct().
84Again, it is important to understand that those temporaries are created at evaluation time only, that is in operator =.
85See TopicPitfalls_auto_keyword for common pitfalls regarding this remark.
Brian Silverman72890c22015-09-19 14:37:37 -040086
Austin Schuhc55b0172022-02-20 17:52:35 -080087<b>The third circumstance</b> in which %Eigen chooses to evaluate a sub-expression, is when its cost model shows that the total cost of an operation is reduced if a sub-expression gets evaluated into a temporary.
88Indeed, in certain cases, an intermediate result is sufficiently costly to compute and is reused sufficiently many times, that is worth "caching". Here is an example:
Brian Silverman72890c22015-09-19 14:37:37 -040089
Austin Schuhc55b0172022-02-20 17:52:35 -080090\code mat1 = mat2 * (mat3 + mat4);
91\endcode
Brian Silverman72890c22015-09-19 14:37:37 -040092
Austin Schuhc55b0172022-02-20 17:52:35 -080093Here, provided the matrices have at least 2 rows and 2 columns, each coefficient of the expression <tt>mat3 + mat4</tt> is going to be used several times in the matrix product. Instead of computing the sum every time, it is much better to compute it once and store it in a temporary variable. %Eigen understands this and evaluates <tt>mat3 + mat4</tt> into a temporary variable before evaluating the product.
Brian Silverman72890c22015-09-19 14:37:37 -040094
95*/
96
97}