Hello everyone. The following simple example is just to ask the question: will Julia evaluate the length function 5 times? Thank you.
function test()
v = [1,2,3,4,5]
for i = 1:length(v)
println(v[i])
end
end
Hello everyone. The following simple example is just to ask the question: will Julia evaluate the length function 5 times? Thank you.
function test()
v = [1,2,3,4,5]
for i = 1:length(v)
println(v[i])
end
end
No
A quick and no-brainer way to check if performance is affected (while not answering your question exactly):
using BenchmarkTools
v = [1:10_000]
function test1(v)
for i = 1:length(v)
println(v[i])
end
end
@btime test1(v)
120.894 ΞΌs (22 allocations: 800 bytes)
function test2(v)
n = length(v)
for i = 1:n
println(v[i])
end
end
@btime test2(v)
121.065 ΞΌs (22 allocations: 800 bytes)
The key thing to understand here is that 1:length(v)
is just an ordinary Julia expression that creates a βrangeβ object storing the endpoints. This object gets evaluated once, before the for
loop starts, and gets re-used on every iteration as needed.
More generally, whenever you do for x = X
or (equivalently) for x in X
, for any expression X
, the expression X
is evaluated once and then the resulting iterable object is re-used during the loop.
I only knew @time
, I liked @btime
, very good!
I tend to avoid the combination of @btime
and println
. How far do you have to scroll back up to compare the results?
In the OPβs code, itβs just something to do inside the loop.
julia> length(v)
1
Though your example is still valid perhaps you meant v=[i for i in 1:10_000]
?
perhaps you meant
v=[i for i in 1:10_000]
?
I meant something big thatβs all.
You can see it explicitely with:
julia> function test()
v = [1,2,3,4,5]
for i = 1:length(v)
println(v[i])
end
end
test (generic function with 1 method)
julia> @code_lowered test()
CodeInfo(
1 β v = Base.vect(1, 2, 3, 4, 5)
β %2 = Main.length(v)
β %3 = 1:%2
β @_2 = Base.iterate(%3)
β %5 = @_2 === nothing
β %6 = Base.not_int(%5)
βββ goto #4 if not %6
2 β %8 = @_2
β i = Core.getfield(%8, 1)
β %10 = Core.getfield(%8, 2)
β %11 = Base.getindex(v, i)
β Main.println(%11)
β @_2 = Base.iterate(%3, %10)
β %14 = @_2 === nothing
β %15 = Base.not_int(%14)
βββ goto #4 if not %15
3 β goto #2
4 β return nothing
)