[Insight-developers] Image/ImageAdaptor/DataAccessor modification
Luis Ibanez
ibanez@cs.unc.edu
Fri, 16 Mar 2001 11:13:21 -0500
Hi,
The questions raised by Josh's tests are quite relevant.
Let's consider them in order:
1) The difference in execution time between:
a- ImageIterator (the one not supporting adaptors) and
b- ImageIteratorWithIndex (the one supporting adaptors)
when no data is accessed, are due to the computation of the index.
(a) is faster because it doesn't keep an updated value of the index,
that's good because it doesn't penalize the user for something he
is not using. Should the user require to access the index, then (b)
will be faster because the index is updated progressively.
So far, this differences are not related to the fact of supporting
adaptors or not, as Josh correctly noted. The time corrections that
Josh did are a perfect compensation for this difference in nature
between the two iterators. So, the time comparisions after
compensation are fair.
2) The differences found in gcc in Linux for access to scalars are
surprisingly high. As far as I can see, they seem to be caused
by the fact that the Get() method in the default DataAccessor class
is returning by value (copy) instead of by reference:
TExternalType Get( const TInternalType & value ) const {
return (TExternalType) value; }
So, I just modified to return by const reference like:
const TExternalType & Get( const TInternalType & value ) const {
return (TExternalType) value; }
This is posible only in the default DataAccessor because the
InternalType and the ExternalType are the same. In any other real
DataAccessor, those types will be different, and a temporary copy
of the data will be required, in those cases the return has to be
done by copy; but that's fair because the user will be paying for
the 'cast' which is somethig he is really using.
Curiously SGI do better, and seems to optimize the inlined copy...
3) The vector case is the real difficult point. In fact what make
them special is not that they are vectors, but that they are big
objects and the algorithm needs to modify them 'in place'. For this
case, the Get()/Set() approach is not efficient because it forces
the user to make two additional copies of the object data.
It seems that the best solution for this case is exactly what Josh
proprosed: "Bypass the data accessor".
It is hard to argue otherwise given that this is in the heart of
access to image data, and will affect the overall performance of
the toolkit.
The option is then, to provide an additional method for accessing
pixel data. The use of this method will be justified when data
should be modified in place, like the += vector operation in Josh's
example. In any other cases, when data is only read or only writen,
there is not real penalty in using the Get()/Set() methods.
The additional access method could be the * operator, like was
originaly, of something like the Value() method in the VectorContainer
iterators.
*it += vectorInc; or it.Value() += vectorInc;
The * operator seems to be a more natural choice, which could be bad,
because programmers will have more tendency to use it even if the can
use Set()/Get() and support adaptors. The Value() method has the
advantage of giving a uniform aspect to all the interators on the
toolkit, and that it will force programmers to think if they really
need Value() or can go with Set()/Get().
What are your preferences ?
Note that supporting Adaptors is specially important in the input
and output of filters, but any other computation performed on
images declared internally can count on the real nature of the
images (unless the type of the input or output has been used to
declare them, a case which also needs further discussion...).
Thanks,
Luis
PS.
Unfortunately I'll not be able to make the TCon today.
I'll appreciate if somebody can summarize the feedback
from other people and the discussion on this topic
today, and post it to the list. Sorry about that.