# global variable
v = rand(10000)
function fun1()
s = 0.0
for i in v::Vector{Float64}
s += i
end
end
function fun2(x::Vector{Float64})
s = 0.0
for i in x
s += i
end
end
I think fun2 has a better form, it should has better performance. But
# fun1
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 1.800 ns … 4.700 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 1.800 ns ┊ GC (median): 0.00%
Time (mean ± σ): 1.850 ns ± 0.110 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
█ ▄
█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂ ▂
1.8 ns Histogram: frequency by time 2 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
# fun2
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 4.400 ns … 29.100 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 4.500 ns ┊ GC (median): 0.00%
Time (mean ± σ): 4.500 ns ± 0.383 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
█
▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃ ▂
4.4 ns Histogram: frequency by time 4.6 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
fun2 is slower than fun1.
========== Appendix ==========
> @code_llvm fun1()
; @ In[11]:1 within `fun1'
; Function Attrs: uwtable
define void @julia_fun1_2323() #0 {
top:
; @ In[11]:3 within `fun1'
%0 = load atomic {}*, {}** inttoptr (i64 254897432 to {}**) unordered, align 8
%1 = bitcast {}* %0 to i64*
%2 = getelementptr inbounds i64, i64* %1, i64 -1
%3 = load atomic i64, i64* %2 unordered, align 8
%4 = and i64 %3, -16
%5 = inttoptr i64 %4 to {}*
%6 = icmp eq {}* %5, inttoptr (i64 1802763472 to {}*)
br i1 %6, label %pass, label %fail
fail: ; preds = %top
call void @jl_type_error(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @_j_str1, i64 0, i64 0), {}* inttoptr (i64 1802763472 to {}*), {}* %0)
unreachable
pass: ; preds = %top
; @ In[11]:4 within `fun1'
ret void
}
> @code_llvm fun2()
; @ In[12]:1 within `fun2'
; Function Attrs: uwtable
define nonnull {}* @japi1_fun2_2411({}* %0, {}** %1, i32 %2) #0 {
top:
%3 = alloca {}**, align 8
store volatile {}** %1, {}*** %3, align 8
; @ In[12]:4 within `fun2'
ret {}* inttoptr (i64 1800907472 to {}*)
}
show me an example where eliminating non-const global variables hurts performance, because that’s what “risk much higher” is equivalent to in this analogy
I recommend against the bad practice (in your analogy, eating unhealthy food), you’re saying my recommendation may lead to worse results. (in your analogy, higher risk?)
clearly this is never the case for Julia, if you don’t have non-const globals, you can’t have any weird/slow code, to begin with.
the “wrong thing” in OP was not how the functions are written, it’s having non-const globals, DON’T HAVE NON-CONST GLOBAL.
all the rest are derived symptoms, I don’t care what f1 and f2 are, and how some bad f1 (related to non-const global) is faster than a different bad f2 (again related to non-const global), just don’t do non-const global.
So you’re saying results don’t matter, only ideology matters. The sacred book says so, and you shouldn’t care that doing the wrong thing reduces your runtime by a factor of 3…