From: Ian McCulloch (ianmcc_at_[hidden])
Date: 2005-06-22 08:49:50
Michael Stevens wrote:
> On Monday 20 June 2005 11:44, Ian McCulloch wrote:
>> A global switch like that would be a mistake, IMHO. It would make it
>> impossible to combine uBLAS functions from different sources while sill
>> retaining performance, and force people wanting to write portable code to
>> ALWAYS use either alias() or noalias() on every expression.
> Agreed. The ability to combine uBLAS functions from different sources is
> fundamental to me.
>> However, something that might be useful is a global option to force
>> alias() to be always on (ie, force 'safe' execution, even if noalias is
>> specified), for debug checking.
> Interesting idea. Something like BOOST_UBLAS_CHECK_NOALIAS perhaps?
>> Perhaps it would be better to move the alias policy into the containers?
>> The way I see it, you can think of an expression such as
>> Vector x,y;
>> Matrix M;
>> x += M*x + y;
>> in two ways:
>> As an array expression, it is essentially a shorthand for
>> for (i = 0; i < N; ++i)
>> x[i] += inner_prod(M[i], x) + y[i];
>> here the aliasing problem is obvious.
>> Alternatively, if you view it as an expression over a ring (or R-module,
>> or whatever), you would expect it to behave the same way as if x,y,M were
>> simple numbers, and x += M*x + y should 'just work'.
> Agreed. Two different way of view the problem.
>> So, how about
>> Vector<double> x; // default: forces 'safe' handling of aliases
>> Vector<double, noalias> y; // fast: user takes responsibility for aliases
> Syntacticly this is elegant but allowing container semantics to change is
The containers have some different behaviour, but then so do
vector/deque/list. That doesn't stop us writing generic code, you just
need to be aware of what the containers allow.
> In generic code this brakes your portable code criteria. For example
> template <class V>
> multA (V& l, const V& r)
> l = prod (A, r);
> Without knowing it's implementation it is impossible to know if 'multA (y,
> y)' is correct.
Sure. But is this really any different to
template <class Container>
void foo(Container& c)
typename Container::iterator a = c.begin();
typename Container::iterator b = a;
c.erase(b); // undefined behaviour? maybe!
But we can have BOOST_MPL_ASSERT(not_alias<V>) (or is_restricted<V> might be
a better name), so the function author can check that it is being called
correctly. I don't see this as any different to having a container
algorithm assert that the supplied container has appropriate iterator
invalidation semantics (although I think it is not possible to detect
>> These would be roughly analagous to C99 restricted and non-restricted
>> double x;
>> double y[restrict];
>> in their expression semantics.
> Although both vary the semantics I think C99 has an advantage over uBLAS
> in this case. The restrict arrays only effect the semantics of a few
> aliased pointer operations. uBLAS has to deal with the lvalue aliases.
Not sure what you mean here.
> A separate topic. It would be interesting to how much optimisation a
> compiler of C++ with 'restrict' could gain when compiling uBLAS.
> It would be easy in uBLAS to enforce 'restrict' internally and I suspect
> it would help optimise expression evaluation a lot.