Is there way to circshift an array with undef element. When this is tried, below is the exception thrown.
julia> a = Vector{Vector{Float64}}(undef, 3)
a3-element Array{Array{Float64,1},1}:
#undef
#undef
#undef
julia> a[1] = rand(2)
2-element Array{Float64,1}:
0.7169372111930692
0.7575125123881752
julia> a
3-element Array{Array{Float64,1},1}:
[0.7169372111930692, 0.7575125123881752]
#undef
#undef
julia> circshift(a, 1)
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getindex at ./array.jl:728 [inlined]
[2] macro expansion at ./multidimensional.jl:925 [inlined]
[3] macro expansion at ./cartesian.jl:64 [inlined]
[4] macro expansion at ./multidimensional.jl:924 [inlined]
[5] copyto!(::Array{Array{Float64,1},1}, ::CartesianIndices{1,Tuple{UnitRange{Int64}}}, ::Array{Array{Float64,1},1}, ::CartesianIndices{1,Tuple{UnitRange{Int64}}}) at ./multidimensional.jl:912
[6] _circshift! at ./multidimensional.jl:995 [inlined]
[7] _circshift! at ./multidimensional.jl:990 [inlined]
[8] circshift!(::Array{Array{Float64,1},1}, ::Array{Array{Float64,1},1}, ::Tuple{Int64}) at ./multidimensional.jl:961
[9] circshift(::Array{Array{Float64,1},1}, ::Int64) at ./abstractarraymath.jl:181
[10] top-level scope at REPL[4]:1
julia>
Any ideas how can this be succeeded?
You should generally not rely on the behavior of non-initialized arrays, and only use them, if you’re fully initializing it before you do anything else with it. It would be helpful to know, what you are trying to achieve. You might want to use nothing
here instead.
1 Like
Arrays with undefined elements should normally only be used if you immediately want to initialize them. If you want to actually do processing on the array (e.g. circshift
) while it still contains undefined elements, then probably you actually want to use missing
or nothing
values for some of the elements.
e.g. you could use
a = fill!(Vector{Union{Nothing,Vector{Float64}}}(undef, 3), nothing)
a[1] = rand(2)
circshift(a, 1)
to get
3-element Array{Union{Nothing, Array{Float64,1}},1}:
nothing
[0.8598233150587076, 0.08394105932185103]
nothing
Whether you using missing
or nothing
depends upon what you are doing. missing
is usually employed in statistics when there is missing data in a dataset—data that exists in principle but is unknown—and nothing
is typically used for other kinds of unavailable values (e.g. not-yet-initialized array members).
4 Likes
What about the performance of using a vector whose elements are Union types?
The compiler can optimize these small unions in arrays quite efficiently, see https://julialang.org/blog/2018/08/union-splitting. But of course, there will always be some penalty, so you should do your own benchmarking if this is performance-critical.
3 Likes
See also this blog post on the Missing
type — years of effort went into the compiler in part to support arrays of Union{Missing,Foo}
for representing statistical data, and this has had spillover benefits in many other areas.
3 Likes
Here is a small benchmark. It seems that performance is not affected in the case of using union types.
julia> using BenchmarkTools
julia> function f()
array = Vector{Vector{Float64}}(undef, 1000)
for i = 1 : 1000
array[i] = rand(2)
end
end
f (generic function with 1 method)
julia> function g()
array = Vector{Union{Nothing, Vector{Float64}}}(undef, 1000)
for i = 1 : 1000
array[i] = rand(2)
end
end
g (generic function with 1 method)
julia> f()
julia> g()
julia> @benchmark f()
BenchmarkTools.Trial:
memory estimate: 101.69 KiB
allocs estimate: 1001
--------------
minimum time: 34.395 μs (0.00% GC)
median time: 35.836 μs (0.00% GC)
mean time: 46.298 μs (17.39% GC)
maximum time: 32.995 ms (99.85% GC)
--------------
samples: 10000
evals/sample: 1
julia> @benchmark g()
BenchmarkTools.Trial:
memory estimate: 101.69 KiB
allocs estimate: 1001
--------------
minimum time: 34.497 μs (0.00% GC)
median time: 35.950 μs (0.00% GC)
mean time: 46.587 μs (18.22% GC)
maximum time: 34.925 ms (99.86% GC)
--------------
samples: 10000
evals/sample: 1
julia>
2 Likes