[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.