-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
make Printf's general format C11 compliant #40689
Conversation
Hmmmm, would you mind posting some benchmarks? It seems unfortunate that we'd have to call |
I quickly benchmarked the performance with the following script: using Random
Random.seed!(1234)
N = 500_000
x = [randn(N); exp.(randn(N) * 100)]
shuffle!(x)
using Printf
function g6(out, x)
for xx in x
@printf out "%.6g" xx
end
end
using BenchmarkTools
@btime g6($devnull, $x) PR:
master (8fdd137):
Surely it slowed the throughput down, but the difference is not devastating, which was much smaller than I expected. I agree that this should be fixed inside Ryu, but if it takes time I think this slowdown is tolerable for the time being. |
Even if fixed-point and scientific cases are segregated, the result seems to be the same: using Random
Random.seed!(1234)
N = 500_000
x = randn(N)
y = exp.(randn(N) * 100)
z = shuffle!([x; y])
using Printf
function g6(out, x)
for xx in x
@printf out "%.6g" xx
end
end
using BenchmarkTools
@btime g6($devnull, $x)
@btime g6($devnull, $y)
@btime g6($devnull, $z) PR:
master:
|
I'm a bit skeptical of this result. Maybe I'm doing something wrong. Could anyone reproduce? |
7b98824
to
c33877f
Compare
#40755 should be merged before this change. |
Here are the results I get. master: julia> @btime g6($devnull, $x)
163.121 ms (2000000 allocations: 411.99 MiB)
julia> @btime g6($devnull, $x)
80.925 ms (1000000 allocations: 205.99 MiB)
julia> @btime g6($devnull, $y)
78.093 ms (1000000 allocations: 205.99 MiB)
julia> @btime g6($devnull, $z)
165.143 ms (2000000 allocations: 411.99 MiB) PR: julia> @btime g6($devnull, $x)
194.712 ms (2000000 allocations: 411.99 MiB)
julia> @btime g6($devnull, $x)
81.821 ms (1000000 allocations: 205.99 MiB)
julia> @btime g6($devnull, $y)
107.219 ms (1000000 allocations: 205.99 MiB)
julia> @btime g6($devnull, $z)
196.549 ms (2000000 allocations: 411.99 MiB) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I'm fine merging because it at least fixes the rounding cases w/o too bad performance hit. The solution just feels bad though, because we're using writeexp
just to get the exponent, then twiddling w/ that to figure out if we should do writefixed
or writeexp
. And we're not even using writeshortest
any more, which has a bunch of the same logic builtin.
But it's fine; it's tricky code to dig into, and like I said, the perf here isn't bad at all, so we should merge it for now.
Thank you! |
Would this be good to backport? In that case, please add the backport label. |
In general, rounding a floating-point number before formatting is considered harmful, because it may introduce some rounding error. As an extreme example, the largest normal number
1.7976931348623157e308
cannot be correctly formatted with precision 1 if we round it before sending it to Ryu, because the rounded result would be larger than the largest representable number, as shown below:N1570 (the final draft of C11, §7.21.6.1, page 313) defines the general format (
%g
and%G
) as follows:This PR makes the general format follow this standard. It may make the format slower because the current algorithm formats the same number twice in order to get the exponent part. I couldn't come up with a better way.
Also, this fixes #39748.
EDIT: This depends on #40685 to pass tests.