ReadOnlyMemoryError with SubArray

I’m getting a ReadOnlyMemoryError from:

julia> t .-= t[1]
ERROR: ReadOnlyMemoryError()
Stacktrace:
 [1] - at ./float.jl:397 [inlined]
 [2] _broadcast_getindex_evalf at ./broadcast.jl:578 [inlined]
 [3] _broadcast_getindex at ./broadcast.jl:551 [inlined]
 [4] getindex at ./broadcast.jl:511 [inlined]
 [5] macro expansion at ./broadcast.jl:843 [inlined]
 [6] macro expansion at ./simdloop.jl:73 [inlined]
 [7] copyto! at ./broadcast.jl:842 [inlined]
 [8] copyto! at ./broadcast.jl:797 [inlined]
 [9] materialize!(::SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true}, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(-),Tuple{SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true},Float64}}) at ./broadcast.jl:756
 [10] top-level scope at none:0

julia> typeof(t)
SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true}

I can’t reproduce the error with

parent = rand(100)
t = view(parent, 1:100)
t .-= t[1]

despite the fact that the two ts (my original one and this one) have the same types and dimensions.

But, I’ve created a MWE (involving the real data that causes this), it’s just 5 LOC, requires JuliaDB & DataDeps (to fetch the data), and is available as a gist here.

Hope someone can figure out where the problem is!

you are trying to assign into an embedded view and such views are ReadOnly (perhaps)

That was what I thought, but why then does this work?

parent = rand(100)
t = view(parent, 1:100)
t .-= t[1]

view(A, inds…)

Like getindex, but returns a view into the parent array A with the given indices instead of making a copy. Calling getindex or setindex! on the returned SubArray computes the indices to the parent array on the fly without checking bounds.

where it can get to the parent array and the parent array itself is not a something (pbly)

What, so if the parent array is “not accessible” somehow, mutating it is impossible? And that’s what’s happening here? Seems fragile a bit, but OK.

my best guess … others will know more

Fair enough, thanks!!!

You’ll see this if you have a readonly memory-mapped array — those are just plain old Arrays, but they’re readonly. Thus their views are also readonly.

It’s not so much about the SubArray as it is where the original Array came from. SubArrays happily support both read-only and read/write arrays, but are of course constrained by the capabilities of array they view.

1 Like

Thanks, this makes sense. I’ll investigate further up to see what the parent array was. Thanks for the clarification!

when you figure out how to make it work – pls post the solution

Well, in my specific case, the parent data (that the subarray was viewing to) is a JuliaDB.table that is the result of a couple of joins of JuliaDB.tables, all of which were loaded from binary (via JuliaDB.load). So, the question is, are loaded JuliaDB.tables readonly, and if so, should they be?

I simply solved it by avoiding the operation altogether. In my case it was a normalization I could simply avoid. But in all other cases it would have been fine to just allocate to a new vector:

t_new = t .- t[1]