[ITK] [ITK-dev] About the last optimization on VariableLengthVector
Luc Hermitte
luc.hermitte at c-s.fr
Tue Nov 17 03:46:44 EST 2015
Le 16/11/2015 19:44, Matt McCormick a écrit :
> On Mon, Nov 16, 2015 at 8:55 AM, Luc Hermitte <luc.hermitte at c-s.fr> wrote:
>
>>>> Third Problem: Local Variables
>>>> 3.1- Auxiliary variables
>>>> Some algorithms (e.g. BSplines interpolations) require dynamic data
>>>> structures like matrices. This implies allocation at each iteration.
>>>> This particular problem isn't addressed in this patch. The solution to
>>>> 3.2 will help to provide an solution.
>>>>
>>>> 3.2- Factorized computations
>>>> [...]
>>>>
>>>> We need a C++98 solution.
>>>> The only way I see is to rely on cached variables.
>>>> This means that the ImageFunctions are no longer [[pure]] functions :
>>>> they'll mutate some variables that we want to allocate once per
>>>> ImageFunction and ... per thread.
>>>> Indeed the ImageFunctions shall be reentrant.
>>>>
>>>> I was first hoping to use thread_local variables. Alas they cannot be
>>>> non-static attributes. This is a problem: if I'm not wrong, a same
>>>> ImageFunction could be used multiple times in a same processing chain.
>>>>
>>>> We still have a simple solution, but it requires a second modification
>>>> to Evaluate() signature: we need to pass the current ThreadId.
>>>>
>>>> The new drawback: code migration requires more work. We can not write
>>>> Evaluate() in terms of EvaluateNoCopy() as the latter requires the
>>>> threadId that the former doesn't know. This is the reason why I expect
>>>> the tests to fail.
>>>> Instead we need to convert all client code (like the WarpImageFilter)
>>>> and have the default implementation of EvaluateNoCopy() to call the
>>>> already written and not yet converted Evalutate().
>>>
>>> This would be messy, and it would not work very well since the
>>> ImageFunction's are not involved in orchestration of the threading.
>>> Instead, it would be better to make the necessary auxiliary variables
>>> private variables. Parallel code that uses ImageFunction's should
>>> create one ImageFunction instance per thread.
>>
>> I'm afraid that with this choice, code that currently works well in
>> parallel won't work anymore. End users will need to rewrite all uses of
>> image functions in order to use them in MT code. And I guess we will
>> also need to rewrite several test cases.
>>
>> Unless we duplicate the Evaluate() code : i.e. unless we keep the
>> current version, and we add the new and optimized rewrite (for VLV in
>> most cases, or for every kind of variables in some other cases (e.g.
>> BSpline interpolation where caching matrix allocations helps reduce
>> computation time))
>> Duplicating image function algorithms doesn't seem to be a good choice
>> either.
>
> Right. Yes, this will not be maintainable.
>
> A feasible way forward seems to use a C++11 code path when available
> that has enhanced performance (i.e., use auto with C++11). The C++98
> version will not be as fast, but it will work. ITK leans towards
> readability, maintainability, and program-ability over performance in
> cases like this.
With this solution, we loose computation factorizations.
auto p4 = p0 + (p1 - p0) * d0
auto p5 = p2 + (p3 - p2) * d1
output = p4 + (p5 - p4) * d2
p4 computations will be done twice on VLVs and std::valarrays.
// I suppose the dangling reference issue solved.
Using cached variables and introducing a new threadId parameter greatly
improve computation on VLV. But also on some other algorithms.
Readability and maintainability won't be that reduced.
>>>> Fourth Problem: heterogeneous data types (i.e. castings)
>>>> The input image type, the output image type, and the internal pixel type
>>>> may all be different. That's why the code contain so many static_casts.
>>>>
>>>> Alas a static_cast<> on pixels will induce the creation of new pixel values.
>>>> This is contrary to the purpose of this patch.
>>>> Copy constructors and assignment operators already support on-the-fly
>>>> implicit static_casting.
>>>> We still need to be able to require casting only when it's required.
>>>> That's where the new function CastInto(), MoveInto() and As() come into
>>>> rescue.
>>>
>>> So compiler's are not intelligent to make a static_cast<> a no-op when
>>> the types are the same?
>>
>> Unfortunately, it doesn't seem so. Check
>> http://stackoverflow.com/questions/19106826/can-static-cast-to-same-type-introduce-runtime-overhead
>
> Thanks for the link. That thread seems to indicate that POD types are
> not an issue, and non-POD types may not be an issue outside of -O0.
>
>
>> Moreover, in the case of converting VLV<double> to VLV<int>, with a
>> static_cast, we'll force the creation of a new variable which is what I
>> striving to avoid.
>>
>> Hence the new helper functions that'll use the converting assignment
>> operators in case of VLV, or static_cast in all other cases.
>
> Sounds reasonable.
>
> What are the different definitions and uses for CastInto(),
> MoveInto(), and As()?
MoveInto will try to swap() the content of two heavy variables like VLV
when both are of the same type and equivalent to lvalues. If they are
VLV but if their ValueTypes differ, the on-the-fly converting assignment
operator is used. Otherwise, static_cast is used.
The objective is not to use C++11 std::move as for the moment it isn't
implemented as a move-and-swap, but as a destructive move.
CastInto is to be used when swap cannot be used.
This is the case when one of the pixel is actually a proxy/pixel_view.
(i.e. when m_ManageMemory == false). Swapping pixels would alter the
input image, this is unacceptable. Hence, CastInto.
Both could be used independently of Expression Templates.
As<> produces an expression template (on VLV) that will eventually
execute a static_cast on each pixel component. On other types, it
becomes a simple static_cast.
--Luc
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Kitware offers ITK Training Courses, for more information visit:
http://kitware.com/products/protraining.php
Please keep messages on-topic and check the ITK FAQ at:
http://www.itk.org/Wiki/ITK_FAQ
Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/insight-developers
More information about the Community
mailing list