-
Notifications
You must be signed in to change notification settings - Fork 47
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
Fatal performance degradation due to precompilation or inference bugs #496
Comments
Conversionsv0.12.8
🆗 : no problem with v0.12.8 and master masterTBD 🍐 : repaired in master scriptusing Random
using Colors
rgb_f64 = rand(RGB{Float64}, 1000, 1000);
rgb_f32 = rand(RGB{Float32}, 1000, 1000);
hsv_f64 = HSV.(rgb_f64);
hsv_f32 = HSV.(rgb_f32);
xyz_f64 = XYZ.(rgb_f64);
xyz_f32 = XYZ.(rgb_f32);
lab_f64 = Lab.(xyz_f64);
lab_f32 = Lab.(xyz_f32);
lchab_f64 = LCHab.(lab_f64);
lchab_f32 = LCHab.(lab_f32);
luv_f64 = Luv.(xyz_f64);
luv_f32 = Luv.(xyz_f32);
lchuv_f64 = LCHuv.(luv_f64);
lchuv_f32 = LCHuv.(luv_f32);
c64 = (rgb_f64, hsv_f64, xyz_f64, lab_f64, lchab_f64, luv_f64, lchuv_f64);
c32 = (rgb_f32, hsv_f32, xyz_f32, lab_f32, lchab_f32, luv_f32, lchuv_f32);
Cs = shuffle([RGB, HSV, XYZ, Lab, LCHab, Luv, LCHuv]);
for C in Cs
println(C)
for cs in c64
@show C, typeof(cs)
convert.(C, cs);
@time convert.(C, cs);
end
println()
for cs in c32
@show C, typeof(cs)
convert.(C, cs);
@time convert.(C, cs);
end
println()
end
|
Other functionsThese strongly depend on the history of compilations, making it difficult to reproduce the problem
|
This problem may have something to do with the recent discussion in JuliaLang/julia#38983 (and JuliaLang/julia#41872). Edit: However, I don't think the invalidation is directly related to the problem, although there is a similarity in that "unnecessary" inference is re-run. |
Does it occur reproducibly for you? And does it really depend on precompilation? For me I get this: julia> using Colors, BenchmarkTools, Profile # Colors.jl v0.12.8
julia> rgb_f64 = rand(RGB{Float64}, 1000, 1000);
julia> @btime convert.(XYZ, $rgb_f64);
57.859 ms (2000002 allocations: 83.92 MiB)
julia> @btime convert.(XYZ, $rgb_f64);
28.995 ms (2 allocations: 22.89 MiB)
(Colors) pkg> st
Project Colors v0.12.8
Status `~/.julia/dev/Colors/Project.toml`
[3da002f7] ColorTypes v0.11.0 `~/.julia/dev/ColorTypes`
[53c48c17] FixedPointNumbers v0.8.4
[189a3867] Reexport v1.0.0
julia> versioninfo()
Julia Version 1.8.0-DEV.353
Commit 2ab83f6c78* (2021-08-13 14:24 UTC)
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-12.0.1 (ORCJIT, skylake)
Environment:
JULIA_CPU_THREADS = 4 Moreover, I can comment out the The poor performance correlates with seeing @profile @btime convert.(XYZ, $rgb_f64); # do this on the first run when the slowdown happens
open("/tmp/proftree.txt", "w") do io
Profile.print(IOContext(io, :displaysize=>(200,200)), C=true)
end Then open that
|
Perhaps you are using julia> using Colors # master (9c55e4a)
julia> lchab = rand(LCHab, 1000, 1000);
julia> @time convert.(RGB{Float64}, lchab);
0.363478 seconds (4.68 M allocations: 184.190 MiB, 29.44% gc time, 40.76% compilation time)
julia> @time convert.(RGB{Float64}, lchab);
0.095460 seconds (4.00 M allocations: 144.959 MiB, 5.01% gc time)
julia> versioninfo()
Julia Version 1.8.0-DEV.345
Commit 73e5522003 (2021-08-13 18:33 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-12.0.1 (ORCJIT, tigerlake) |
If you are more interested in fixing bugs in Julia and improving analysis tools than in the performance of Colors, the following MWE may be useful for you. |
BTW, in our development flow, we bump up the dependencies just before releasing the minor versions. However, it may be better to tackle this problem with |
Fixed by JuliaLang/julia#43990 |
This is the follow-up to issue #425.
If precompilation is enabled (default), some functions will be boxed, causing significant performance degradation. For example:
This is a bug in Julia, although it has not been clearly identified, and several related issues have been reported.
Core.Compiler.return_type
JuliaLang/julia#35800"#35800" is often used as a synonym of this problem because of the memorability of the issue number.
I am not familiar with Julia's internals, so this looks very strange to me. However, I know a few things empirically.
Perhaps the root cause is that inferencing is context-dependent. A typical example of context-dependency is inlining. Inlining encourages constant propagation and makes inferences more likely to succeed.
We can't spend infinite time on the inference, so interrupting inferencing in a deep method chain is inevitable. The problem is that once a method fails to be inferred, it is marked as an "inference failure" until it is recompiled.
Perhaps Julia v1.6.x, the next LTS candidate, will not fully solve this problem. So we will have to live with this bug.
Of course,
__precompile__(false)
is a valid workaround. However, it is a last resort. There are two major approaches to workarounds. One is to make it easier for the inference to succeed (regardless of the context). The other is to avoid using "marked" (and likely to be "marked") functions.I have implemented several workarounds in Colors v0.13 series, but the problems still remain.
Edit:
A new package JETTest.jl may have less side effects than the runtime-dispatch detection based on benchmarks (such as
@btime
).https://discourse.julialang.org/t/ann-jettest-jl-advanced-testing-toolset-for-julia/63229
The text was updated successfully, but these errors were encountered: