How to optimize such a program

struct TightBindingModel
    norbits::Int64
    lat::Matrix{Float64}
end

function makesupercell(t::TightBindingModel, scrdlat::Matrix{Int64})
    ucs = Vector{Vector{Int64}}()
    scrdlatinv = inv(scrdlat)
    for k in minimum(scrdlat[3, :]):maximum(scrdlat[3, :])
        for j in minimum(scrdlat[2, :]):maximum(scrdlat[2, :])
            for i in minimum(scrdlat[1, :]):maximum(scrdlat[1, :])
                sccoord = scrdlatinv*[i, j, k]
                if all(sccoord.>=0) && all(sccoord.<1)
                    push!(ucs, [i, j, k])
                end
            end
        end
    end
    nucs = length(ucs)
    sc = TightBindingModel(t.norbits*nucs, t.lat*scrdlat)
    return sc
end

lat = eye(3)
t = TightBindingModel(2, lat)

@time makesupercell(t, [200 0 0; 0 200 0; 0 0 1])
# 0.225212 seconds (930.47 k allocations: 714.314 MiB, 24.75% gc time)

This is a simplified version of my Hop.jl library. I expect the performance should be significantly better than python but they are just comparable. I think 24.75% gc time usually means type instability but I cannot find anything in my code that changes type. Also I am having trouble with understanding @code_warntype makesupercell(t, [200 0 0; 0 200 0; 0 0 1]).

  1. Can anyone recoganize the problem of the above program?
  2. Can anyone explain @code_warntype to me? I understand there is an example in official documents but this program is much more complex than the one in documents.

I don’t actually see any type-stability issues with your code, but I do see some potential performance problems. You are correct that memory allocations can result from type instability, but they can also result from just allocating a lot of memory for various other reasons. In particular, you’re doing a lot of things that allocate new vectors:

  • you’re doing minimum(scrdlat[1, :]):maximum(scrdlat[1, :]) inside every iteration of your innermost loop. The problem with this is that scrdlat[1, :] creates a new vector to hold that slice. You’re doing that at every iteration, which is extremely expensive.
  • you’re doing a lot of vector math in your innermost loop. That’s totally fine, but since you know that all of your [i, j, k] vectors will be exactly three elements, you can use the really excellent StaticArrays.jl package to store those vectors much much more efficiently.

Just making two changes (moving the range computation out of the loop and using StaticArrays, I get):

using StaticArrays

struct TightBindingModel
    norbits::Int64
    lat::Matrix{Float64}
end

function makesupercell(t::TightBindingModel, scrdlat::Matrix{Int64})
    ucs = Vector{SVector{3, Int64}}()
    scrdlatinv = SMatrix{3, 3}(inv(scrdlat))
    ranges = [
        minimum(scrdlat[1, :]):maximum(scrdlat[1, :]),
        minimum(scrdlat[2, :]):maximum(scrdlat[2, :]),
        minimum(scrdlat[3, :]):maximum(scrdlat[3, :])
    ]
    for k in ranges[3]
        for j in ranges[2]
            for i in ranges[1]
                ijk = SVector(i, j, k)
                sccoord = scrdlatinv*ijk
                if all(sccoord.>=0) && all(sccoord.<1)
                    push!(ucs, ijk)
                end
            end
        end
    end
    nucs = length(ucs)
    sc = TightBindingModel(t.norbits*nucs, t.lat*scrdlat)
    return sc
end

lat = eye(3)
t = TightBindingModel(2, lat)

using BenchmarkTools
@btime makesupercell($t, [200 0 0; 0 200 0; 0 0 1])

which runs in:

563.434 ÎĽs (40 allocations: 3.00 MiB)

or ~500 times faster.

6 Likes

That’s amazing. Yet, I notice that memory allocations are significantly reduced by using StaticArrays. How come? Creating an SVector does not need memory?

An SVector of a “bits” type is itself a “bits” type. Bitstype objects in Julia can be allocated on the stack, so they don’t create heap memory allocations (which is what the “allocations” that @time shows you actually measures).

The bitstype distinction is subtle but can be important for really high-performance Julia code. The function isbits(T) will tell you if a type T is a bitstype: https://docs.julialang.org/en/stable/stdlib/base/#Base.isbits

Fortunately, the designers of StaticArrays have already done all the hard work for you here, so you don’t need to worry much about the exact semantics of a bitstype.

1 Like

Or, to be more precise, a bitstype is:

  • immutable, AND
  • composed of fields which are either primitive types or other bits types

Thus a regular Vector (which is mutable) is not a bitstype, but an SVector (fixed size, immutable) can be.

Bitstypes behave the same way as any other Julia type (which is a very nice feature of Julia), but the compiler is generally able to allocate them on the stack, so it is cheaper to construct lots of bits types in a loop than non-bits types.

1 Like

Thank you, I understand it now.

Yet, still, when I check the code with @code_warntype. Some of the variables are of type Any, I don’t understand why.

Variables:
  #self#::#makesupercell
  t::TightBindingModel
  scrdlat::Array{Int64,2}
  #1::##1#3
  #2::##2#4
  i::Int64
  ijk::SVector{3,Int64}
  sccoord::SVector{3,Float64}
  #temp#@_9::Int64
  j::Int64
  #temp#@_11::Int64
  k::Int64
  #temp#@_13::Int64
  ucs::Array{SVector{3,Int64},1}
  scrdlatinv::StaticArrays.SArray{Tuple{3,3},Float64,2,9}
  ranges::Array{UnitRange{Int64},1}
  nucs::Int64
  sc::TightBindingModel
  #temp#@_19::Bool
  #temp#@_20::NTuple{9,Float64}
  T::Any
  #temp#@_22::SVector{3,Float64}
  fx@_23::Float64
  fx@_24::Float64
  fx@_25::Float64
  #temp#@_26::SVector{3,Bool}
  #temp#@_27::Bool
  fy@_28::Float64
  fy@_29::Float64
  fy@_30::Float64
  #temp#@_31::SVector{3,Bool}
  #temp#@_32::Bool
  itemT::SVector{3,Int64}
  TS::Any

Body:
  begin 
      NewvarNode(:(nucs::Int64))
      NewvarNode(:(sc::TightBindingModel))
      ucs::Array{SVector{3,Int64},1} = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{SVector{3,Int64},1}, svec(Any, Int64), Array{SVector{3,Int64},1}, 0, 0, 0)) # line 10:
      SSAValue(11) = $(Expr(:invoke, MethodInstance for inv(::Array{Int64,2}), :(Main.inv), :(scrdlat)))
      $(Expr(:inbounds, false))
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/convert.jl Type 4
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/convert.jl convert 21
      unless (Base.not_int)(((Base.arraylen)(SSAValue(11))::Int64 === 9)::Bool)::Bool goto 12 # line 22:
      $(Expr(:invoke, MethodInstance for dimension_mismatch_fail(::Type{T} where T, ::Array{Float64,2}), :(StaticArrays.dimension_mismatch_fail), StaticArrays.SArray{Tuple{3,3},T,2,L} where L where T, SSAValue(11)))
      12:  # line 25:
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/convert.jl unroll_tuple 32
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/convert.jl # line 35:
      $(Expr(:inbounds, true))
      #temp#@_20::NTuple{9,Float64} = (Core.tuple)((Base.arrayref)(SSAValue(11), 1)::Float64, (Base.arrayref)(SSAValue(11), 2)::Float64, (Base.arrayref)(SSAValue(11), 3)::Float64, (Base.arrayref)(SSAValue(11), 4)::Float64, (Base.arrayref)(SSAValue(11), 5)::Float64, (Base.arrayref)(SSAValue(11), 6)::Float64, (Base.arrayref)(SSAValue(11), 7)::Float64, (Base.arrayref)(SSAValue(11), 8)::Float64, (Base.arrayref)(SSAValue(11), 9)::Float64)::NTuple{9,Float64}
      goto 22
      # meta: pop location
      $(Expr(:inbounds, :pop))
      22: 
      # meta: pop location
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/SMatrix.jl Type 33
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/SMatrix.jl # line 37:
      SSAValue(153) = #temp#@_20::NTuple{9,Float64}
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop)) # line 11:
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(111) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(112) = (Base.select_value)((Base.slt_int)(SSAValue(111), 0)::Bool, 0, SSAValue(111))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(123) = 1
      SSAValue(124) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(112), 0)::Bool, 0, SSAValue(112))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(115) = (Core.tuple)(SSAValue(123), SSAValue(124))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(120) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(122) = (Core.getfield)(SSAValue(115), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(116) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(122))::Bool, (Base.sle_int)(SSAValue(122), (Base.select_value)((Base.slt_int)(SSAValue(120), 0)::Bool, 0, SSAValue(120))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(116) goto 76
      goto 78
      76: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(115)))
      78: 
      # meta: pop location # line 442:
      SSAValue(114) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(123), SSAValue(124)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(125) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmin, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmin), :($(QuoteNode(IndexLinear()))), SSAValue(114)))
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(93) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(94) = (Base.select_value)((Base.slt_int)(SSAValue(93), 0)::Bool, 0, SSAValue(93))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(105) = 1
      SSAValue(106) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(94), 0)::Bool, 0, SSAValue(94))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(97) = (Core.tuple)(SSAValue(105), SSAValue(106))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(102) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(104) = (Core.getfield)(SSAValue(97), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(98) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(104))::Bool, (Base.sle_int)(SSAValue(104), (Base.select_value)((Base.slt_int)(SSAValue(102), 0)::Bool, 0, SSAValue(102))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(98) goto 129
      goto 131
      129: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(97)))
      131: 
      # meta: pop location # line 442:
      SSAValue(96) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(105), SSAValue(106)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(126) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmax), :($(QuoteNode(IndexLinear()))), SSAValue(96)))
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(73) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(74) = (Base.select_value)((Base.slt_int)(SSAValue(73), 0)::Bool, 0, SSAValue(73))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(85) = 2
      SSAValue(86) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(74), 0)::Bool, 0, SSAValue(74))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(77) = (Core.tuple)(SSAValue(85), SSAValue(86))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(82) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(84) = (Core.getfield)(SSAValue(77), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(78) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(84))::Bool, (Base.sle_int)(SSAValue(84), (Base.select_value)((Base.slt_int)(SSAValue(82), 0)::Bool, 0, SSAValue(82))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(78) goto 182
      goto 184
      182: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(77)))
      184: 
      # meta: pop location # line 442:
      SSAValue(76) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(85), SSAValue(86)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(87) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmin, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmin), :($(QuoteNode(IndexLinear()))), SSAValue(76)))
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(55) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(56) = (Base.select_value)((Base.slt_int)(SSAValue(55), 0)::Bool, 0, SSAValue(55))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(67) = 2
      SSAValue(68) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(56), 0)::Bool, 0, SSAValue(56))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(59) = (Core.tuple)(SSAValue(67), SSAValue(68))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(64) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(66) = (Core.getfield)(SSAValue(59), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(60) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(66))::Bool, (Base.sle_int)(SSAValue(66), (Base.select_value)((Base.slt_int)(SSAValue(64), 0)::Bool, 0, SSAValue(64))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(60) goto 235
      goto 237
      235: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(59)))
      237: 
      # meta: pop location # line 442:
      SSAValue(58) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(67), SSAValue(68)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(88) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmax), :($(QuoteNode(IndexLinear()))), SSAValue(58)))
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(35) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(36) = (Base.select_value)((Base.slt_int)(SSAValue(35), 0)::Bool, 0, SSAValue(35))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(47) = 3
      SSAValue(48) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(36), 0)::Bool, 0, SSAValue(36))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(39) = (Core.tuple)(SSAValue(47), SSAValue(48))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(44) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(46) = (Core.getfield)(SSAValue(39), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(40) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(46))::Bool, (Base.sle_int)(SSAValue(46), (Base.select_value)((Base.slt_int)(SSAValue(44), 0)::Bool, 0, SSAValue(44))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(40) goto 288
      goto 290
      288: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(39)))
      290: 
      # meta: pop location # line 442:
      SSAValue(38) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(47), SSAValue(48)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(49) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmin, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmin), :($(QuoteNode(IndexLinear()))), SSAValue(38)))
      # meta: location abstractarray.jl getindex 882
      $(Expr(:inbounds, false))
      # meta: location indices.jl to_indices 213
      # meta: location abstractarray.jl indices 64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      SSAValue(17) = (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location indices.jl to_indices 215
      # meta: location multidimensional.jl to_indices 416
      # meta: location multidimensional.jl uncolon 423
      # meta: location indices.jl Type 233
      # meta: location indices.jl Type 233
      # meta: location range.jl convert 764
      SSAValue(18) = (Base.select_value)((Base.slt_int)(SSAValue(17), 0)::Bool, 0, SSAValue(17))::Int64
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(29) = 3
      SSAValue(30) = $(Expr(:new, Base.Slice{Base.OneTo{Int64}}, :($(Expr(:new, Base.OneTo{Int64}, :((Base.select_value)((Base.slt_int)(SSAValue(18), 0)::Bool, 0, SSAValue(18))::Int64))))))
      $(Expr(:inbounds, false))
      # meta: location multidimensional.jl _getindex 438
      # meta: location multidimensional.jl # line 441:
      SSAValue(21) = (Core.tuple)(SSAValue(29), SSAValue(30))::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}
      # meta: location abstractarray.jl checkbounds 362
      # meta: location abstractarray.jl checkbounds 342
      # meta: location abstractarray.jl indices 64
      SSAValue(26) = (Base.arraysize)(scrdlat::Array{Int64,2}, 1)::Int64
      (Base.arraysize)(scrdlat::Array{Int64,2}, 2)::Int64
      # meta: pop location
      # meta: location abstractarray.jl checkbounds_indices 389
      SSAValue(28) = (Core.getfield)(SSAValue(21), 1)::Int64
      # meta: pop location
      # meta: pop location
      SSAValue(22) = (Base.and_int)((Base.and_int)((Base.sle_int)(1, SSAValue(28))::Bool, (Base.sle_int)(SSAValue(28), (Base.select_value)((Base.slt_int)(SSAValue(26), 0)::Bool, 0, SSAValue(26))::Int64)::Bool)::Bool, true)::Bool
      unless SSAValue(22) goto 341
      goto 343
      341: 
      $(Expr(:invoke, MethodInstance for throw_boundserror(::Array{Int64,2}, ::Tuple{Int64,Base.Slice{Base.OneTo{Int64}}}), :(Base.throw_boundserror), :(scrdlat), SSAValue(21)))
      343: 
      # meta: pop location # line 442:
      SSAValue(20) = $(Expr(:invoke, MethodInstance for _unsafe_getindex(::IndexLinear, ::Array{Int64,2}, ::Int64, ::Base.Slice{Base.OneTo{Int64}}), :(Base._unsafe_getindex), :($(QuoteNode(IndexLinear()))), :(scrdlat), SSAValue(29), SSAValue(30)))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      SSAValue(50) = $(Expr(:invoke, MethodInstance for _mapreduce(::Base.#identity, ::Base.#scalarmax, ::IndexLinear, ::Array{Int64,1}), :(Base._mapreduce), :(Base.identity), :(Base.scalarmax), :($(QuoteNode(IndexLinear()))), SSAValue(20)))
      ranges::Array{UnitRange{Int64},1} = $(Expr(:invoke, MethodInstance for vect(::UnitRange{Int64}, ::Vararg{UnitRange{Int64},N} where N), :(Base.vect), :($(Expr(:new, UnitRange{Int64}, SSAValue(125), :((Base.select_value)((Base.sle_int)(SSAValue(125), SSAValue(126))::Bool, SSAValue(126), (Base.sub_int)(SSAValue(125), 1)::Int64)::Int64)))), :($(Expr(:new, UnitRange{Int64}, SSAValue(87), :((Base.select_value)((Base.sle_int)(SSAValue(87), SSAValue(88))::Bool, SSAValue(88), (Base.sub_int)(SSAValue(87), 1)::Int64)::Int64)))), :($(Expr(:new, UnitRange{Int64}, SSAValue(49), :((Base.select_value)((Base.sle_int)(SSAValue(49), SSAValue(50))::Bool, SSAValue(50), (Base.sub_int)(SSAValue(49), 1)::Int64)::Int64)))))) # line 16:
      SSAValue(0) = (Base.arrayref)(ranges::Array{UnitRange{Int64},1}, 3)::UnitRange{Int64}
      #temp#@_13::Int64 = (Core.getfield)(SSAValue(0), :start)::Int64
      356: 
      unless (Base.not_int)((#temp#@_13::Int64 === (Base.add_int)((Core.getfield)(SSAValue(0), :stop)::Int64, 1)::Int64)::Bool)::Bool goto 569
      SSAValue(154) = #temp#@_13::Int64
      SSAValue(155) = (Base.add_int)(#temp#@_13::Int64, 1)::Int64
      k::Int64 = SSAValue(154)
      #temp#@_13::Int64 = SSAValue(155) # line 17:
      SSAValue(2) = (Base.arrayref)(ranges::Array{UnitRange{Int64},1}, 2)::UnitRange{Int64}
      #temp#@_11::Int64 = (Core.getfield)(SSAValue(2), :start)::Int64
      365: 
      unless (Base.not_int)((#temp#@_11::Int64 === (Base.add_int)((Core.getfield)(SSAValue(2), :stop)::Int64, 1)::Int64)::Bool)::Bool goto 567
      SSAValue(156) = #temp#@_11::Int64
      SSAValue(157) = (Base.add_int)(#temp#@_11::Int64, 1)::Int64
      j::Int64 = SSAValue(156)
      #temp#@_11::Int64 = SSAValue(157) # line 18:
      SSAValue(4) = (Base.arrayref)(ranges::Array{UnitRange{Int64},1}, 1)::UnitRange{Int64}
      #temp#@_9::Int64 = (Core.getfield)(SSAValue(4), :start)::Int64
      374: 
      unless (Base.not_int)((#temp#@_9::Int64 === (Base.add_int)((Core.getfield)(SSAValue(4), :stop)::Int64, 1)::Int64)::Bool)::Bool goto 565
      SSAValue(158) = #temp#@_9::Int64
      SSAValue(159) = (Base.add_int)(#temp#@_9::Int64, 1)::Int64
      i::Int64 = SSAValue(158)
      #temp#@_9::Int64 = SSAValue(159) # line 19:
      ijk::SVector{3,Int64} = $(Expr(:new, SVector{3,Int64}, :((Core.tuple)(i, j, k)::Tuple{Int64,Int64,Int64}))) # line 20:
      $(Expr(:inbounds, false))
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/matrix_multiply.jl * 32
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/matrix_multiply.jl _A_mul_B 66
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/matrix_multiply.jl # line 79:
      $(Expr(:inbounds, true))
      SSAValue(161) = (Base.add_float)((Base.add_float)((Base.mul_float)((Base.getfield)(SSAValue(153), 1)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 1)::Int64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 4)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 2)::Int64)::Float64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 7)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 3)::Int64)::Float64)::Float64)::Float64
      SSAValue(162) = (Base.add_float)((Base.add_float)((Base.mul_float)((Base.getfield)(SSAValue(153), 2)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 1)::Int64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 5)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 2)::Int64)::Float64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 8)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 3)::Int64)::Float64)::Float64)::Float64
      SSAValue(163) = (Base.add_float)((Base.add_float)((Base.mul_float)((Base.getfield)(SSAValue(153), 3)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 1)::Int64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 6)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 2)::Int64)::Float64)::Float64)::Float64, (Base.mul_float)((Base.getfield)(SSAValue(153), 9)::Float64, (Base.sitofp)(Float64, (Base.getfield)((Core.getfield)(ijk::SVector{3,Int64}, :data)::Tuple{Int64,Int64,Int64}, 3)::Int64)::Float64)::Float64)::Float64
      goto 395
      # meta: pop location
      $(Expr(:inbounds, :pop))
      395: 
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop)) # line 21:
      $(Expr(:inbounds, false))
      # meta: location broadcast.jl broadcast 434
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl broadcast_c 33
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl _broadcast 52
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl # line 110:
      $(Expr(:inbounds, true))
      SSAValue(130) = SSAValue(161)
      $(Expr(:inbounds, false))
      # meta: location  #1 0
      $(Expr(:inbounds, false))
      # meta: location operators.jl >= 261
      # meta: location float.jl <= 486
      fx@_25::Float64 = (Base.sitofp)(Float64, 0)::Float64
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(129) = SSAValue(162)
      $(Expr(:inbounds, false))
      # meta: location  #1 0
      $(Expr(:inbounds, false))
      # meta: location operators.jl >= 261
      # meta: location float.jl <= 486
      fx@_24::Float64 = (Base.sitofp)(Float64, 0)::Float64
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(128) = SSAValue(163)
      $(Expr(:inbounds, false))
      # meta: location  #1 0
      $(Expr(:inbounds, false))
      # meta: location operators.jl >= 261
      # meta: location float.jl <= 486
      fx@_23::Float64 = (Base.sitofp)(Float64, 0)::Float64
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(165) = (Base.or_int)((Base.lt_float)(fx@_25::Float64, SSAValue(130))::Bool, (Base.and_int)((Base.eq_float)(fx@_25::Float64, SSAValue(130))::Bool, (Base.or_int)((Base.eq_float)(fx@_25::Float64, 9.223372036854776e18)::Bool, (Base.sle_int)(0, (Base.fptosi)(Int64, fx@_25::Float64)::Int64)::Bool)::Bool)::Bool)::Bool
      SSAValue(166) = (Base.or_int)((Base.lt_float)(fx@_24::Float64, SSAValue(129))::Bool, (Base.and_int)((Base.eq_float)(fx@_24::Float64, SSAValue(129))::Bool, (Base.or_int)((Base.eq_float)(fx@_24::Float64, 9.223372036854776e18)::Bool, (Base.sle_int)(0, (Base.fptosi)(Int64, fx@_24::Float64)::Int64)::Bool)::Bool)::Bool)::Bool
      SSAValue(167) = (Base.or_int)((Base.lt_float)(fx@_23::Float64, SSAValue(128))::Bool, (Base.and_int)((Base.eq_float)(fx@_23::Float64, SSAValue(128))::Bool, (Base.or_int)((Base.eq_float)(fx@_23::Float64, 9.223372036854776e18)::Bool, (Base.sle_int)(0, (Base.fptosi)(Int64, fx@_23::Float64)::Int64)::Bool)::Bool)::Bool)::Bool
      goto 449
      # meta: pop location
      $(Expr(:inbounds, :pop))
      449: 
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      $(Expr(:inbounds, false))
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/mapreduce.jl all 212
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/mapreduce.jl reduce 163
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/mapreduce.jl mapreduce 67
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/mapreduce.jl _mapreduce 84
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/mapreduce.jl # line 91:
      $(Expr(:inbounds, true))
      #temp#@_27::Bool = (Base.and_int)((Base.and_int)((Base.and_int)(true, SSAValue(165))::Bool, SSAValue(166))::Bool, SSAValue(167))::Bool
      goto 466
      # meta: pop location
      $(Expr(:inbounds, :pop))
      466: 
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      unless #temp#@_27::Bool goto 541
      $(Expr(:inbounds, false))
      # meta: location broadcast.jl broadcast 434
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl broadcast_c 33
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl _broadcast 52
      # meta: location /home/wangc/.julia/v0.6/StaticArrays/src/broadcast.jl # line 110:
      $(Expr(:inbounds, true))
      SSAValue(137) = SSAValue(161)
      $(Expr(:inbounds, false))
      # meta: location  #2 0
      $(Expr(:inbounds, false))
      # meta: location float.jl < 491
      fy@_30::Float64 = (Base.sitofp)(Float64, 1)::Float64
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(136) = SSAValue(162)
      $(Expr(:inbounds, false))
      # meta: location  #2 0
      $(Expr(:inbounds, false))
      # meta: location float.jl < 491
      fy@_29::Float64 = (Base.sitofp)(Float64, 1)::Float64
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(135) = SSAValue(163)
      $(Expr(:inbounds, false))
      # meta: location  #2 0
      $(Expr(:inbounds, false))
      # meta: location float.jl < 491
      fy@_28::Float64 = (Base.sitofp)(Float64, 1)::Float64
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))

This is not the full output. I cannot post it since due to the limit of length of posts, but the omitted part does not contain any type warnings.

Now I am not sure how smart the compiler is, but to find minimum and maximum, this may be two passes over the data (in your code).
If you use extrema(yourmatrixorarowthereof) that might find min and max in one pass…
Not sure if that is the case , I cannot try this out right now…

1 Like

If you see variables of type Any in the list of variables, but they don’t show up in the Body section, then they’ve been eliminated by the compiler and you can safely ignore them. You’re just seeing an artifact of the various optimizations that the compiler performs. I believe those ::Any variables will be removed in v0.7.

2 Likes