Re: [boost] [review] Multiprecision review scheduled for June 8th - 17th, 2012

Let us know as soon as you have some results.
Tested the time taken to run through all the Boost.Math Bessel function tests, with type double, real_concept (a simple wrapper around double from Boost.Math's test suite) and mp_number<float_backend<double> > (a trivial mp_number backend that wraps a floating point type):
Time for double = 0.0157549 seconds Time for real_concept = 0.0166421 seconds Time for float_backend<double> = 0.0408635 seconds Time for float_backend<double> - no expression templates = 0.0253047 seconds
So as you can see, expression templates are a dis-optimization for such simple types, and even without them you take a noticeable hit: I'm a little disappointed by this, but not that surprised, mp_number is a rather heavyweight solution for lightweight types if you see what I mean.
In any case I'll have a look at the assembly to see if there are any obvious non-optimizations going on.
From a quick casual look it appears as though the extra time is going in functions not expanded inline - that's certainly the case for the expression template unpacking code. Seems like there may be some small opportunity for optimization of the comparison operators as well (i.e. not evaluating in terms of a compare() function). However, that latter case is only appropriate for exceptionally lightweight backends, for most typical extended precision backends, non of this will make the slightest difference at all...
John.

On Tue, Jun 5, 2012 at 3:38 AM, John Maddock <boost.regex@virgin.net> wrote:
Let us know as soon as you have some results.
Tested the time taken to run through all the Boost.Math Bessel function tests, with type double, real_concept (a simple wrapper around double from Boost.Math's test suite) and mp_number<float_backend<**double> > (a trivial mp_number backend that wraps a floating point type):
Time for double = 0.0157549 seconds Time for real_concept = 0.0166421 seconds Time for float_backend<double> = 0.0408635 seconds Time for float_backend<double> - no expression templates = 0.0253047 seconds
So as you can see, expression templates are a dis-optimization for such simple types, and even without them you take a noticeable hit: I'm a little disappointed by this, but not that surprised, mp_number is a rather heavyweight solution for lightweight types if you see what I mean.
In any case I'll have a look at the assembly to see if there are any obvious non-optimizations going on.
From a quick casual look it appears as though the extra time is going in
functions not expanded inline - that's certainly the case for the expression template unpacking code. Seems like there may be some small opportunity for optimization of the comparison operators as well (i.e. not evaluating in terms of a compare() function). However, that latter case is only appropriate for exceptionally lightweight backends, for most typical extended precision backends, non of this will make the slightest difference at all...
Hasn't Eric had some issues with Boost.Proto not being fully inlined by some compilers in the past (or maybe still in the present)? And/or having to explicit decorate some Boost.Proto functions with some kind of "force inline"? - Jeff

On Tue, 5 Jun 2012, John Maddock wrote:
Let us know as soon as you have some results.
Tested the time taken to run through all the Boost.Math Bessel function tests, with type double, real_concept (a simple wrapper around double from Boost.Math's test suite) and mp_number<float_backend<double> > (a trivial mp_number backend that wraps a floating point type):
Time for double = 0.0157549 seconds Time for real_concept = 0.0166421 seconds Time for float_backend<double> = 0.0408635 seconds Time for float_backend<double> - no expression templates = 0.0253047 seconds
Out of curiosity, what compiler/options? I know from similar experiments that it can play a huge role, and only with the highest optimizations (profile feedback and all) were the performances the same. In other cases the abstraction penalty never disappeared.
Seems like there may be some small opportunity for optimization of the comparison operators as well (i.e. not evaluating in terms of a compare() function).
Is this related? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51938 By the way, compare is required to return int, but sometimes it would be more convenient if I could use long (for the same reason you picked int and not an enum {-1,0,1}). Or even double. Do you do anything with the result of compare that works better because it is an int? I might even want to use a proxy. -- Marc Glisse

Tested the time taken to run through all the Boost.Math Bessel function tests, with type double, real_concept (a simple wrapper around double from Boost.Math's test suite) and mp_number<float_backend<double> > (a trivial mp_number backend that wraps a floating point type):
Time for double = 0.0157549 seconds Time for real_concept = 0.0166421 seconds Time for float_backend<double> = 0.0408635 seconds Time for float_backend<double> - no expression templates = 0.0253047 seconds
Out of curiosity, what compiler/options? I know from similar experiments that it can play a huge role, and only with the highest optimizations (profile feedback and all) were the performances the same. In other cases the abstraction penalty never disappeared.
It's VC++ 10 with /Ox. As you can see the abstraction penalty for real_concept (which is about as simple a wrapper as you can get) just about but not quite disappears, but is still there for the more complex mp_number.
Seems like there may be some small opportunity for optimization of the comparison operators as well (i.e. not evaluating in terms of a compare() function).
Is this related? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51938
Yes, though I confess I wasn't expecting compiler to make the optimisation you suggest - I'm very impressed that clang can!!
By the way, compare is required to return int, but sometimes it would be more convenient if I could use long (for the same reason you picked int and not an enum {-1,0,1}). Or even double. Do you do anything with the result of compare that works better because it is an int? I might even want to use a proxy.
Good point - I think the result of my_backend::compare can be any integer or enum type - it must be comparable with a literal zero (for the comparison ops), and convertible to int (for mp_number::compare). But I think it would be a legitimate optimization for the return type to be the same type as a limb in the internal representation. Cheers, John.
participants (3)
-
Jeffrey Lee Hellrung, Jr.
-
John Maddock
-
Marc Glisse