Trying to understand output of @code_warntype

In the output of @code_warntype I’m getting a @_6::Union{Nothing, Tuple{Int64,Int64}} that I don’t understand. Here’s a MWE

# Monte Carlo tolerancing

using Random, Distributions, LabelledArrays

"named tuple of distributions of dimensions"
var_dists = (dimA = Truncated(Normal(100, 1.5), 97, 103),
             dimB = Truncated(Normal(106, 1.5), 103, 109))
        
"labelled vector to store sample of dimensions"
vars = @LVector Float64 keys(var_dists)

"takes a sample of the dimensional variables"
function sample_vars!(vars, var_dists)
    for key in keys(var_dists)
        vars[key]=rand(var_dists[key])
    end
end

"compute the resultant for this sample"
function resultant(v)
    v.dimB+v.dimA
end

function simulate(vars, var_dists)
    N = 10000
    r=Vector{Float64}(undef,N)
    for i in 1:N
        sample_vars!(vars, var_dists)
        r[i] = resultant(vars)
    end
    return r
end

@time v=simulate(vars, var_dists)
@code_warntype(simulate(vars, var_dists))

which produces

0.100398 seconds (110.13 k allocations: 7.468 MiB, 3.96% gc time)
Variables
  #self#::Core.Compiler.Const(simulate, false)
  vars::LArray{Float64,1,Array{Float64,1},(:dimA, :dimB)}
  var_dists::NamedTuple{(:dimA, :dimB),Tuple{Truncated{Normal{Float64},Continuous},Truncated{Normal{Float64},Continuous}}}
  N::Int64
  r::Array{Float64,1}
  @_6::Union{Nothing, Tuple{Int64,Int64}}
  i::Int64

Body::Array{Float64,1}
1 ─       (N = 10000)
│   %2  = Core.apply_type(Main.Vector, Main.Float64)::Core.Compiler.Const(Array{Float64,1}, false)
│         (r = (%2)(Main.undef, N::Core.Compiler.Const(10000, false)))
│   %4  = (1:N::Core.Compiler.Const(10000, false))::Core.Compiler.Const(1:10000, false)
│         (@_6 = Base.iterate(%4))
│   %6  = (@_6::Core.Compiler.Const((1, 1), false) === nothing)::Core.Compiler.Const(false, false)
│   %7  = Base.not_int(%6)::Core.Compiler.Const(true, false)
└──       goto #4 if not %7
2 ┄ %9  = @_6::Tuple{Int64,Int64}::Tuple{Int64,Int64}
│         (i = Core.getfield(%9, 1))
│   %11 = Core.getfield(%9, 2)::Int64
│         Main.sample_vars!(vars, var_dists)
│   %13 = Main.resultant(vars)::Float64
│         Base.setindex!(r, %13, i)
│         (@_6 = Base.iterate(%4, %11))
│   %16 = (@_6 === nothing)::Bool
│   %17 = Base.not_int(%16)::Bool
└──       goto #4 if not %17
3 ─       goto #2
4 ┄       return r

Thanks!

My guess is that you’re seeing an internal variable introduced by the iteration protocol (calling iterate() on 1:N will either return a Tuple{Int, Int} or Nothing depending on whether the iterator has reached its end). The compiler in Julia 1.x is very good at handling these kinds of small unions, so unless this is actually causing a problem for you I would not worry about it at all. You can learn more about the new iterator interface here: https://julialang.org/blog/2018/07/iterators-in-julia-0.7

2 Likes

Note that the output for the variable is printed in yellow to indicate that this is probably not a problem.

1 Like

Interesting - I wouldn’t have called that yellow - I would have called it a muddy red (doesn’t help that I’m deuteranomalous), but inspecting the object in my browser says it’s ansi-yellow-intense-fg. In any case it’s the only splash of color on the page.

Well, we tell the terminal to print it as yellow at least :).