@threads fails when interating over a dictionary

Trying to parallelise over a dictionary iterator fails.

using Base.Threads

d = Dict("a" => 1, "b" => 2)

@threads for (k, v) in d
  println("$(k) => $(v)")
end

produces

ERROR: TaskFailedException
Stacktrace:
 [1] wait
   @ ./task.jl:334 [inlined]
 [2] threading_run(func::Function)
   @ Base.Threads ./threadingconstructs.jl:38
 [3] top-level scope
   @ ./threadingconstructs.jl:97

    nested task error: MethodError: no method matching firstindex(::Dict{String, Int64})
    Closest candidates are:
      firstindex(::Any, ::Any) at ~/Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/abstractarray.jl:396
      firstindex(::AbstractChar) at ~/Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/char.jl:200
      firstindex(::UnitRange) at ~/Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/base/range.jl:646
      ...
    Stacktrace:
     [1] (::var"#3#threadsfor_fun#5"{Dict{String, Int64}})(onethread::Bool)
       @ Main ./threadingconstructs.jl:70
     [2] (::var"#3#threadsfor_fun#5"{Dict{String, Int64}})()
       @ Main ./threadingconstructs.jl:52

There are obvious workarounds but it was a bit surprising to me.

this is because @threads loop needs fixed indexing space and dictionary doesn’t have one. you probably want to use collect here

3 Likes