This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch, libfortran] PR 52434/48878/38199 Improve floating point formatted writes


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]