[Patch, libfortran] PR 52434/48878/38199 Improve floating point formatted writes
Jerry DeLisle
jvdelisle@charter.net
Wed Mar 14 23:53:00 GMT 2012
On 03/08/2012 05:40 PM, Janne Blomqvist wrote:
> Hi,
>
> the attached patch implements some improvements for formatted writes
> of floating point values. Currently libgfortran uses snprintf() to
> fill a buffer with a fixed amount of digits, regardless of the digits
> required, and then rounding or zero extending as needed. The patch
> changes this to first figure out the number of digits needed, then
> using snprintf() to fill the buffer with exactly the needed amount of
> digits (except when a ROUND= specifier is used, in that case more
> digits are generated). This has a few advantages:
>
> - As the performance cost of snprintf() increases roughly linearly
> with more digits (see
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38199#c13 ), we needlessly
> waste cycles when we don't need all the digits. The attached
> write-many.f90 benchmark is almost twice as fast; best of five timings
> with current trunk:
>
> real 0m2.055s
>
> with patch:
>
> real 0m1.268s
>
>
> - Although we generate enough digits to be able to get back the
> original value exactly when reading, there are some (valid?) usecases
> where more digits are needed. Exhibit 1 is dyadic.f90 which prints a
> couple dyadic fractions which are exact both in binary and character
> representations. With current trunk:
>
> $ ./dyadic_f
> .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
> .99999999999999988897769753748434595763683000000000000
>
> With patch:
>
> $ ./dyadic_f
> .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
> 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
> 00000000000000000000000000000000000000000000000000000000000000000000000000494065645841246544176568792868221372365059802614324
> 76442558568250067550727020875186529983636163599237979656469544571773092665671035593979639877479601078187812630071319031140452
> 78458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566
> 86768187039560310624931945271591492455329305456544401127480129709999541931989409080416563324524757147869014726780159355238611
> 55013480352649347201937902681071074917033322268447533357208324319360923828934583680601060115061698097530783422773183292479049
> 82524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993
> 664809941164205702637090279242767544565229087538682506419718265533447265625
> .99999999999999988897769753748434595763683319091796875
>
> For another example, Bob Corbett recently posted boz_corbett.f90 on
> c.l.f. With trunk:
>
> $ ./boz_corbett
> .67242062862241870125253556346435045576786000...E-4931
>
> where "..." is a very long string of zeros. With patch:
>
> $ ./boz_corbett
> .672420628622418701252535563464350455767864674589043138777375863685283014882452413061808444374167...E-4931
>
> where "..." is a very long string of digits.
>
> - With the patch, for the vast majority of Fortran programs which
> don't use the F2003 ROUND= specifier, we let snprintf() do the
> rounding (as we generate the correct number of digits to begin with).
> Thus isolating the user from potential bugs in the rounding logic in
> libgfortran, as well as the performance impacts of that same code.
>
> Note that GFortran previously did roundTiesToAway, whereas at least
> glibc snprintf() does roundTiesToEven, so some change in behavior is
> expected. Anyway, this is IMHO for the better, as it avoids biasing
> the magnitude upwards in some common cases. Also, roundTiesToAway is
> the default rounding mode for arithmetic.
>
> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
I like the idea behind this patch. I confess, I have not studied the two test
cases that you are modifying, but the changes seem to stick out with too many
digits there. Is this really correct?
When I get another moment, I will look closer. Maybe you can explain the need
for this change a little more. Sorry if I am being to careful. Its been many
months since I delved into the formatting code.
Best regards,
Jerry
More information about the Fortran
mailing list