保证检测临时->命名点

Guaranteed Detection of Temporary->Named Points

假设你用一些操作写了一个矩阵class:

class matrix
{
public:
    double operator()(size_t i, size_t j) const;
    ...
};

matrix operator*(const matrix &lhs, const matrix &rhs);
...

延迟某些矩阵表达式的计算是有意义的:m0 * m1 * m2 * m3 * m4(这是一系列四个 operator* 调用)可以受益于使用 dynamic-programming matrix chain multiplication algorithm; the very common m0 * m1t has a very efficient dgemm implementation,等等。

因此,将实际计算推迟到需要的时候是值得的。这会将上面的内容更改为:

class matrix
{
private:
    /*
    * Pointer to an abstract base class - either an actual matrix, 
    *    or an expression tree. */
    std::shared_ptr<matrix_imp> m_imp;

public:
    // Forces compaction - 
    double operator()(size_t i, size_t j) const;
    ...
};

/* Lazy; creates a matrix with an expression tree using the
*    internals of lhs and rhs. */
matrix operator*(const matrix &lhs, const matrix &rhs);
...

每个矩阵都包含一个指向基础 class 对象的指针,该对象的范围可以从实际矩阵到复杂的表达式树。每个操作都尝试使用对内部实现的最懒惰的更改来形成一个矩阵。有些操作别无选择,只能实际评估事物,压缩表达式树,并将内部实现设置为实际矩阵。


问题是,在实践中,这在非常常见的情况下会导致巨大的内存开销。假设您从文件中读取了一个狭长矩阵 x = xp X q, p >> q, store xtx一个变量,丢弃x。使用惰性求值,内存为 pq >> qq。循环加载这些,这是一个严重的问题。 (当然,客户端代码调用 operator() 可以在每次加载后强制执行压缩,但是在没有算法证明的情况下要求这样做是丑陋且容易出错的。)

最初,我认为 move ctor 是自动压缩的好点 - 它正是临时成为命名对象的地方,它是导致内存消耗增加的命名对象,所以

matrix(matrix &&other); // <- Force compaction only here

似乎可以解决所有问题,例如

auto res = // <- temp becoming named
    a * // temp
    b * // temp
    c + // temp
    2 * // temp
    d;

但是可以指望吗?例如,考虑

matrix load_xtx(const string &f_name)
{
    matrix x = ...
    return x.t() * x; 
}

auto xtx = load_xtx("foo.hdf5"); // (*)

编译器是否被禁止在 (*) 中执行类似于它在 NRVO 中执行的操作,即仅在适当的位置构造它?即使没有,编译器是否可以优化其他情况下的东西?

由于"internal pointer" 方法无法提供延迟求值所需的全部灵活性,C++ 数值库使用的典型解决方案是定义专门的类 实现惰性求值机制。旧的 SO 问题 Lazy evaluation in C++ 及其最佳答案显示了此类设计的基础知识和一些示例代码。

虽然我不是专家,但我认为这种架构的很好的例子是数字库 Eigen(here some details about its implementation) and Blitz++, which heavily relies on templates (I did not find on the web updated documentation illustrating its internals, but this article 描述了它的引擎的某些部分,还提供了 "expression template" 技术的更广泛的概述).