On Jul 31, 2014, at 9:38 AM, John Ralls <jra...@ceridwen.us> wrote:

> 
> On Jul 31, 2014, at 7:13 AM, Geert Janssens <i...@kobaltwit.be> wrote:
> 
>> On Saturday 19 July 2014 11:53:37 John Ralls wrote:
>>> The libmpdecimal branch now passes make check all the way through.
>>> I've force-pushed a rebase on the latest master to
>>> https://github.com/jralls/gnucash.git for anyone who'd like to play
>>> with it.
>>> 
>>> Next step is to do some tuning to see how much I can shrink it while
>>> getting full 64-bit coefficients (current tests limit it to 44-bits)
>>> then profiling to see if there are any performance differences to
>>> master.
>>> 
>>> Regards,
>>> John Ralls
>>> 
>>> 
>>> _______________________________________________
>>> gnucash-devel mailing list
>>> gnucash-devel@gnucash.org
>>> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
>> 
>> Nice! Keep up the good work.
>> 
>> I'm curious to hear about the performance difference. Hopefully the 
>> performance will be better :)
> 
> Libmpdecimal is about 25% slower as it is now, but I see some good 
> optimization opportunities from the profile. I'm also looking at the Intel 
> and GCC/ICU versions to see if they might prove faster, since mpdecimal is 
> written specifically for Python and so has some extra overhead that doesn't 
> seem to be present in the others.
> 
> The Intel version is particularly interesting because it uses a different 
> encoding scheme and dispenses with contexts, both of which they claim afford 
> much faster execution. Unfortunately their code is rather impenetrable and 
> the documentation is sparse and difficult to understand. It also doesn't 
> appear to expose an interface that can be used to extract a rational 
> expression of the number, so it would require more code changes in the rest 
> of GnuCash to be useable.
> 
> Removing the 44-bit clamp and increasing the range of the denominators from 
> 10^6 to 10^9 passes all tests except test-lots, which fails from being unable 
> to balance the lots in complex cases. I'm still debugging that.

So, having gotten test-lots and all of the other tests working* with 
libmpdecimal, I studied the Intel library for several days and couldn't figure 
out how to make it work, so I decided to try the GCC implementation, which 
offers a 128-bit IEEE 754 format that's fixed size. Since it doesn't ever call 
malloc, I thought it might prove faster, and indeed it is. I haven't finished 
integrating it -- the library doesn't provide formatted printing -- but it's 
far enough along that it passes all of the engine and backend tests. Some 
results:

test-numeric, with NREPS increased to 20000 to get a reasonable execution time 
for profiling:
    master     9645ms
    mpDecimal 21410ms
    decNumber 12985ms

test-lots:
    master      16300ms
    mpDecimal   20203ms
    decNumber   19044ms

The first shows the relative speed in more or less pure computation, the latter 
shows the overall impact on one of the longer-running tests that does a lot of 
other stuff. 

I haven't investigated Christian's other suggestion of aggressive rounding to 
eliminate the overflow issue to make room for larger denominators, nor my 
original idea of replacing gnc_numeric with boost::rational atop a 
multi-precision class (either boost::mp or gmp). I have noticed that we're 
doing some dumb things with Scheme, like using double as an intermediate when 
converting from Scheme numbers to gnc_numeric (Scheme numbers are also 
rational, so the conversion should be direct) and representing gnc_numerics as 
a tuple (num, denom) instead of just using Scheme rationals. Neither will work 
for decimal floats, of course; the whole class will have to be wrapped so that 
computation takes place in C++. Storage in SQL is also an issue, as is 
maintaining backward file compatibility.

Another issue is equality: In order to get tests to pass I've had to implement 
a fuzzy comparison where both numbers are first rounded to the smaller number 
of decimal places -- 2 fewer if there are 12 or more -- and compared with two 
roundings, first truncation and second "bankers", and declared unequal only if 
they're unequal in both. I hate this, but it seems to be necessary to obtain 
equality when dealing with large divisors (as when computing prices or interest 
rates). I suspect that we'd have to do something similar if we pursue 
aggressive rounding to avoid overflows, but the only way to know for certain is 
to try.

I've force-pushed both branches to my github repo for the curious; beware that 
ATM neither passes "make check".

Regards,
John Ralls

* That didn't last long, though: The latest rebase onto master broke some of 
the tests. I haven't fixed them yet because I wanted to get this profiling data 
done.



_______________________________________________
gnucash-devel mailing list
gnucash-devel@gnucash.org
https://lists.gnucash.org/mailman/listinfo/gnucash-devel

Reply via email to