Logo MTL4

Why Not Using Shallow Copy in Numerical Software

Shallow copy has the advantage over deep copy of being considerably faster. This advantage does not justify all the dangers implied.

Unawareness

The first risk is that many programmers are not aware of the aliasing behavior, which is that after the assignment neither of the two arguments can be modified without affecting the other. As one of the two variables can be changed in a sub-function of a sub-function of a ... it is hard to track down all possible modifications.

Type Dependence of Copy behavior

Moreover, the problem is even more confusing. Since shallow copy semantic is only feasible between objects of the same type, assignments between different types must copy data deeply. In generic functions aiming for maximal generality one do not want assume or require equality or distinctness of argument types so that the copy behavior is unknown.

// File: shallow_copy_problems_type.cpp

#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>

using namespace mtl;

int main(int argc, char* argv[])
{
    dense2D<double>     A(3, 3), B(3, 3);
    dense2D<float>      C(3, 3);

    A= 4.0;

    B= A;               // Create an alias
    B*= 2.0;            // Changes also A

    C= A;               // Copies the values
    C*= 2.0;            // A is unaffected

    return 0;
}

Impact of Mathematically Neutral Operations

In the same way mathematically neutral operations like multiplications with one or additions of zero vectors silently change the program behavior by disabling shallow copies and eliminating the aliasing behavior.

A= B;           // Aliasing of A and B
A= 1.0 * B;     // A and B are independent

Code Obfuscation

Many higher level libraries like ITL assigns vectors with the copy function instead of the assignment operator in order to guarantee deep copy.

A= B;           // (Potential) shallow copy
copy(B, A);     // Deep copy

We refrain from this approach because this syntax does not correspond to the mathematical literature and more importantly we cannot be sure that all users of a library will replace assignments by copy.

Undermining const Attributes

Last but not least all shallow copy implementations we have seen so far relentlessly undermined const attributes of arguments.

// File: shallow_copy_problems_const.cpp

#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>

using namespace mtl;


template <typename Matrix>
void f2(Matrix& C)
{
    C= 5.0;
}

// Undermine const-ness of function argument
template <typename Matrix>
double f(const Matrix& A)
{
    Matrix B;
    B= A;
    f2(B);
    return frobenius_norm(A);
}


int main(int argc, char* argv[])
{
    dense2D<double>     A(3, 3);
    A= 4.0;

    double alpha= f(A); // A is changed now!

    return 0;
}

After calling f, A is modified despite it was passed as const argument and the const-ness was not even casted away.

Resume

For all these reasons we are convinced that reliable mathematical software can only be implemented with deep copy semantics. Unnecessary copies can be avoided by using advanced techniques as expression templates and Move Semantics.

Return to Copying in MTL4                                Table of Content                                Proceed to Addicted to peak performance


Why Not Using Shallow Copy in Numerical Software -- MTL 4 -- Peter Gottschling and Andrew Lumsdaine -- Generated on 24 Aug 2009 by Doxygen 1.5.9 -- Copyright 2008-09 by TU Dresden and the Trustees of Indiana University.