Is there a shorter way to write for m₁ in axes(M, 1), m₂ in axes(M, 2) in the code below? m₁ and m₂ are required.
let M = [1 2 3; 4 5 6]
res = Any[]
for m₁ in axes(M, 1), m₂ in axes(M, 2)
push!(res, (M[m₁, m₂]))
end
res
end
Note that the original poster on Slack cannot see your response here on Discourse. Consider transcribing the appropriate answer back to Slack, or pinging the poster here on Discourse so they can follow this thread. (Original message )(More Info)
Just to be sure, the CartesianIndices provide in this case a shorter syntax but they seem to be 2x less performant in terms of allocations and speed compared to OP’s proposal? Tested it for: M = randn(1_000,1_000)
Julia Version 1.6.0-beta1.0 on Win10. Copying test here in case I might be doing something wrong:
M = randn(1_000,1_000)
@btime let # 74 ms (2979998 allocations: 70 MiB)
res = Any[]
for m₂ in axes(M, 2), m₁ in axes(M, 1)
push!(res, (M[m₁, m₂]))
end
end
@btime let # 146 ms (4978020 allocations: 146 MiB)
res = Any[]
for m in CartesianIndices(M)
m₁, m₂ = m[1], m[2]
push!(res, M[m])
end
end
It’s typically easier to just benchmark functions rather than lets… but the key is that you need to flag M as an argument to the benchmark kernel with a $ either way. Otherwise, it’s treated as a non-constant global reference, which can have strange performance effects depending upon how inlining happens.
julia> @btime let # 74 ms (2979998 allocations: 70 MiB)
res = Any[]
for m₂ in axes($M, 2), m₁ in axes($M, 1)
push!(res, ($M[m₁, m₂]))
end
end
11.836 ms (1000020 allocations: 24.26 MiB)
julia> @btime let # 146 ms (4978020 allocations: 146 MiB)
res = Any[]
for m in CartesianIndices($M)
m₁, m₂ = m[1], m[2]
push!(res, $M[m])
end
end
11.574 ms (1000020 allocations: 24.26 MiB)
Of course, now we still have the pessimized storage for the Any[] array, but that just adds ~1ms to each.
@mbauman, thank you for the explanation. pairs() seems to have similar performance in this case: for (m, Mij) in pairs(M) and then use m[1], m[2] and Mij