Boost logo

Ublas :

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
> bad!

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;
   ++b;
   c.erase(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
that?).

>
>>
>> These would be roughly analagous to C99 restricted and non-restricted
>> arrays,
>>
>> 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.

Cheers,
Ian