It returns a pair with the index of the element, and the element of the collection.
Maybe it is even safer to do this:
Threads.@threads for i in eachindex(λ_noms, rel_sigmas)
println("lambda_nom: $(λ_nom[i])")
rel_sigma_ = 100 * rel_sigma(λ_nom=λ_nom[i])
rel_sigmas[i] = rel_sigma_
end
Which will error if the indexes of λ_noms and rel_sigmas are not the same (which I think you expect so).
Indeed, there is the possible complication of the indexes of your lambda_noms not having the same range of indexes than your output vector. If that is not the case, I would probably go with eachindex, to guarantee that applies.
I’m going to be honest; after looking at the docstring for both pairs and enumerate, I think I just got confused about the difference between them . Neither one really guards against issues with mismatched array indices; I absolutely agree that using eachindex is definitely the best practice here.
I guess you’ll see the difference if using an offset array:
julia> x = OffsetArray(1:3, -2)
1:3 with indices -1:1
julia> for (i, val) in pairs(x)
@show i, val
end
(i, val) = (-1, 1)
(i, val) = (0, 2)
(i, val) = (1, 3)
julia> for (i, val) in enumerate(x)
@show i, val
end
(i, val) = (1, 1)
(i, val) = (2, 2)
(i, val) = (3, 3)
Thus enumerate was the right choice there (although both pairs and enumerate are giving the same indexes there), for the code he posted. But if he had initialized with this:
I’m not sure to which extent this example is representative of your real task but, in this case at least, it falls into the category of classical higher order functions (map in this case) and you’d probably be better off using a battle-tested parallel implementation such as what ThreadsX provides:
julia> λ_noms = sort(unique(vcat(7:0.1:9.5, 7.8:0.02:8.2, 7.98:0.005:8.02)));
julia> rel_sigma(x) = exp(rand()*x)
rel_sigma (generic function with 1 method)
julia> using ThreadsX
julia> rel_sigmas = ThreadsX.map(rel_sigma, λ_noms)
48-element Vector{Float64}:
40.6612060246467
16.49068401058819
109.36091646835631
[...]
julia> Threads.@threads for i in eachindex(λ_noms, rel_sigmas)
λ_nom = λ_noms[i]
println("lambda_nom: $(λ_nom)")
rel_sigma_ = 100 * rel_sigma(λ_nom)
rel_sigmas[i] = rel_sigma_
end
lambda_nom: 7.0
lambda_nom: 7.1
lambda_nom: 7.2
lambda_nom: 7.3
(this one requires that λ_noms and rel_sigmas have the same indices)
ps: Using for i in 1:length(λ_noms) would do the same here, without the above guarantee, and possibly failing if the arrays have strange indexing (like offset arrays).
v = LinRange(0,1,20)
Threads.@threads for (i,x) in collect(enumerate(v))
println(x)
end
But yeah, I don’t think is worth the allocation.
It should be nice to make this work without the collect, though. It seems hard because enumerate(x) doesn’t have a supertype and @threads wants a firstindex (easy, as we can do first(enumerate(v))) but also getindex method… Maybe this one is a small thing to add to possible improvements of @threads…