Why isn't a simple map type stable?

Shouldn’t Julia be able to infer that the return type is Vector{Float64} in the example below? prevx is initialized to a Float64 value and randn() returns a Float64 value.

julia> function gen1(n)
        prevx = 0.0
        map(1:n) do _
         x = randn()
         r = prevx + x
         prevx = x
         r
        end
       end
gen1 (generic function with 1 method)

julia> @code_warntype gen1(10)
MethodInstance for gen1(::Int64)
  from gen1(n) in Main at REPL[44]:1
Arguments
  #self#::Core.Const(gen1)
  n::Int64
Locals
  #25::var"#25#26"
  prevx::Core.Box
Body::Vector
1 ─      (prevx = Core.Box())
β”‚        Core.setfield!(prevx, :contents, 0.0)
β”‚        (#25 = %new(Main.:(var"#25#26"), prevx))
β”‚   %4 = #25::var"#25#26"
β”‚   %5 = (1:n)::Core.PartialStruct(UnitRange{Int64}, Any[Core.Const(1), Int64])
β”‚   %6 = Main.map(%4, %5)::Vector
└──      return %6

I believe that is the topic of the following section: performance of captured variables.

2 Likes

yeah this is because you’re modifying that prevx so it needs to be captured, better write it like this:

julia> function gen2(n)
           prevx = 0.0
           res = Vector{Float64}(undef, n)
           for i in eachindex(res)
               x = randn()
               res[i] = prevx + x
               prevx = x
           end
           res
       end

julia> @benchmark gen1(100)
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
 Range (min … max):  2.452 ΞΌs … 113.209 ΞΌs  β”Š GC (min … max): 0.00% … 95.54%
 Time  (median):     3.432 ΞΌs               β”Š GC (median):    0.00%
 Time  (mean Β± Οƒ):   3.565 ΞΌs Β±   3.399 ΞΌs  β”Š GC (mean Β± Οƒ):  2.95% Β±  3.02%

  β–ƒ                                                           β–ˆ
  β–ˆβ–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β– β–ˆ
  3.25 ΞΌs         Histogram: frequency by time        3.36 ΞΌs <

 Memory estimate: 5.67 KiB, allocs estimate: 305.

julia> @benchmark gen2(100)
BenchmarkTools.Trial: 10000 samples with 434 evaluations.
 Range (min … max):  254.009 ns …   1.995 ΞΌs  β”Š GC (min … max): 0.00% … 72.86%
 Time  (median):     309.528 ns               β”Š GC (median):    0.00%
 Time  (mean Β± Οƒ):   332.448 ns Β± 139.497 ns  β”Š GC (mean Β± Οƒ):  3.45% Β±  6.93%

  β–ˆ                                                              
  β–ˆβ–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β–β– ▁▁▁▁▁▁▁▁▁▁▁▁ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▁
  475 ns           Histogram: frequency by time          265 ns <

 Memory estimate: 896 bytes, allocs estimate: 1.
2 Likes