codegen_level="min"
and broadcasting with function arguments result in runtime instability check #57
Open
Description
Consider the following:
using DispatchDoctor: @stable
@stable default_codegen_level="min" function mymap!(f, y, x)
for i in eachindex(y, x)
y[i] = f(x[i])
end
return nothing
end
mymap!
should be a fast, stable, and allocation-free function. Not so:
julia> using BenchmarkTools: @benchmark
julia> include("mymap.jl")
julia> @benchmark mymap!(identity, $(zeros(1000)), $(zeros(1000)))
BenchmarkTools.Trial: 10000 samples with 8 evaluations.
Range (min … max): 3.670 μs … 24.436 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 4.278 μs ┊ GC (median): 0.00%
Time (mean ± σ): 4.451 μs ± 885.102 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▃▄▁▃█▇▄▇█▆▃▄▄▃ ▁ ▂
███████████████▇▇▆▅▅▄▄▄▄▅▇██████▇▇▇▆▇▆▆▇██████▆▅▇▆▅▅▅▄▄▄▂▄▅ █
3.67 μs Histogram: log(frequency) by time 8.25 μs <
Memory estimate: 1.27 KiB, allocs estimate: 16.
The allocations disappear and performance improves by a factor of 40 in either of the following conditions:
- Removing
@stable
- Using
default_codegen_level="debug"
- Adding a type variable for
f
, as infunction mymap!(f::F, y, x) where {F}
The culprit is likely that the generated mymap!
implementation does not specialize on the type of f
, since it's never called in mymap!
's body but only passed to other functions (specializing_typeof;
mymap!_simulator`). Hence the stability check must be performed at runtime, leading to the observed performance and allocation penalty.
Metadata
Assignees
Labels
No labels