Does @threads not allow iteration over Dict()?

I have no idea why the following code errors:

using Base.Threads

A = Dict{Int, Vector{Float64}}()
# A = rand(10, 10) # OK

foreach(i->A[i] = rand(10), 1:10)

@threads for i in eachindex(A)  # ERROR: TaskFailedException in case that A is a Dict()
    sum(A[i])
end

ERROR: TaskFailedException:
MethodError: no method matching unsafe_getindex(::Base.KeySet{Int64,Dict{Int64,Array{Float64,1}}}, ::Int64)
Closest candidates are:
unsafe_getindex(::StepRangeLen{T,#s66,#s65} where #s65<:Base.TwicePrecision where #s66<:Base.TwicePrecision, ::Integer) where T at twiceprecision.jl:447
unsafe_getindex(::StepRangeLen{T,R,S} where S where R, ::Integer) where T at range.jl:647
unsafe_getindex(::LinRange, ::Integer) at range.jl:657

It seems like that @threads does not allow iteration over Dict(); If A is an array e.g., A = rand(10, 10) no such error occurs.

Yeah, the internal implementation of the @threads has trouble with some generators and the like (in this case, a KeySet) due to the unsafe_getindex usage. Try this:

@threads for i in collect(eachindex(A))  # Turns the KeySet into a Vector first
    sum(A[i])
end
2 Likes

How straightforward but clever the idea is! Why didn’t such an idea come to my mind?

1 Like