Hey all!
I’m trying to create an iterator over an array right now that only returns certain elements. The definition of the type looks something like this (all code will be at the bottom):
struct DwellIterAbstract
data::AbstractVector{Float64}
dlast::Int
x_lo::Float64
x_hi::Float64
end
I have a method which I apply to the iterator like so (it’s a little verbose because it makes it easier to read @code_warntype
output):
function is_in_range(dwi::DwellIterAbstract, i)
elem = dwi.data[i]
b1 = dwi.x_lo <= elem
b2 = elem <= dwi.x_hi
return b1 && b2
end
Intutively, I expect that dwi.data[i]
should be Float64
, because dwi.data
is AbstractVector{Float64}
. When I run @code_warntype
on this method however, I get the following:
@code_warntype is_in_range(dwi_abs, 10)
MethodInstance for is_in_range(::DwellIterAbstract, ::Int64)
from is_in_range(dwi::DwellIterAbstract, i::Integer) in Main at /mnt/wdblack-4T/Experiments/10-2022/splitting-on-ring/code/splitting.jl:18
Arguments
#self#::Core.Const(is_in_range)
dwi::DwellIterAbstract
i::Int64
Locals
b2::Any
b1::Any
elem::Any
Body::Any
1 ─ %1 = Base.getproperty(dwi, :data)::AbstractVector{Float64}
│ (elem = Base.getindex(%1, i))
│ %3 = Base.getproperty(dwi, :x_lo)::Float64
│ (b1 = %3 <= elem)
│ %5 = elem::Any
│ %6 = Base.getproperty(dwi, :x_hi)::Float64
│ (b2 = %5 <= %6)
└── goto #3 if not b1
2 ─ return b2
3 ─ return false
Notably, all of elem
, b1
, and b2
are of type Any
. This method gets called a lot in my code, and the allocation alone is sinking my performance (I assume because these Any
values have to be boxed). This seems strange to me because my intuition says that indexing an AbstractVector{Float64}
should definitely return a Float64
, so I’m not sure why it’s giving me Any
.
If I modify this struct so that data
is of type Vector{Float64}
, then the three locals are typed as a Float64
and two Bool
s, but then I lose the ability to use my code on views, or SharedArrays.
Question: Have I misunderstood what the AbstractArray interface promises? Is there any way I can get dwi.data[i]
to result in a Float64?
Full code:
struct DwellIterAbstract
data::AbstractVector{Float64}
dlast::Int
x_lo::Float64
x_hi::Float64
end
struct DwellIterConcrete
data::Vector{Float64}
dlast::Int
x_lo::Float64
x_hi::Float64
end
function is_in_range(dwi::DwellIterAbstract, i::Integer)
elem = dwi.data[i]
b1 = dwi.x_lo <= elem
b2 = elem <= dwi.x_hi
return b1 && b2
end
function is_in_range(dwi::DwellIterConcrete, i)
elem = dwi.data[i]
b1 = dwi.x_lo <= elem
b2 = elem <= dwi.x_hi
return b1 && b2
end
In REPL:
include(<file.jl>)
dwi_abs = DwellIterAbstract(zeros(10_000), 10_000, -1.0, 1.0)
dwi_con = DwellIterConcrete(zeros(10_000), 10_000, -1.0, 1.0)
@code_warntype is_in_range(dwi_abs, 10)
@code_warntype is_in_range(dwi_con, 10)