I’m trying to access linked entries in a sparse matrix where only the values change and thought it would be faster to save the locations of the values, but accessing them like this is much slower than just matrix indexing the sparse matrix and setting the values by hand. Inspecting with @code_warntype
reveals a lot of red lines.
I made the type
mutable struct Observer{T,R}
ref::R
pair::Pair{Int32,Int32}
nzidx1::Int32
nzidx2::Int32
val::T
end
Which I for example initialize as
sp # Some SparseMatrixCSC
ob = Observer(sp, 1=>2, 1, 101, sp.nzval[1])
@code_warntype ob.ref
MethodInstance for getproperty(::Observer{Float32, SparseMatrixCSC{Float32, Int32}}, ::Symbol)
from getproperty(x, f::Symbol) @ Base Base.jl:37
Arguments
#self#::Core.Const(getproperty)
x::Observer{Float32, SparseMatrixCSC{Float32, Int32}}
f::Symbol
Body::Any
1 ─ nothing
│ %2 = Base.getfield(x, f)::Any
└── return %2
Get field seems to be type instable?
Then I’m trying to set them through a dict of these things, and @code_warntype
reveals a lot of red.
function setval(ob::Observer, val)
ob.ref.nzval[ob.nzidx1] = val
ob.ref.nzval[ob.nzidx2] = val
end
struct ObserverList{A, B} <: AbstractDict{A, B}
observers::Dict{A, B}
end
function setval(obs::ObserverList{A,Observer{T,R}}, val, pair) where {A, T, R<:SparseMatrixCSC{T}}
if haskey(obs, pair)
setval(obs[pair], val)
return val
end
return val
end
@code_warntype setval(observers,1, 1=>2)
MethodInstance for setval(::ObserverList{Pair{Int32, Int32}, Observer{Float32}}, ::Int64, ::Pair{Int32, Int32})
from setval(obs::ObserverList, val, pair) @ Main ~/Documents/GitHub/InteractiveRBM.jl/ObserverList.jl:41
Arguments
#self#::Core.Const(setval)
obs::ObserverList{Pair{Int32, Int32}, Observer{Float32}}
val::Int64
pair::Pair{Int32, Int32}
Locals
observer::Observer{Float32}
Body::Union{Nothing, Int64}
1 ─ Core.NewvarNode(:(observer))
│ %2 = Main.haskey(obs, pair)::Bool
└── goto #3 if not %2
2 ─ (observer = Base.getindex(obs, pair))
│ %5 = Base.getproperty(observer, :ref)::SparseMatrixCSC
│ %6 = Base.getproperty(%5, :nzval)::Vector
│ %7 = Base.getproperty(observer, :nzidx1)::Int32
│ Base.setindex!(%6, val, %7)
│ %9 = Base.getproperty(observer, :ref)::SparseMatrixCSC
│ %10 = Base.getproperty(%9, :nzval)::Vector
│ %11 = Base.getproperty(observer, :nzidx2)::Int32
│ Base.setindex!(%10, val, %11)
└── return val
3 ─ return
I’m open to this being a dumb idea, but I am genuinely a bit confused why the code ends up being type instable…