Reputation: 845
For scalars, the \
(solve linear system) operator is equivalent to the division operator /
. Is the performance similar?
I ask because currently my code has a line like
x = (1 / alpha) * averylongfunctionname(input1, input2, input3)
Visually, it is important that the division by alpha
happens on the "left," so I am considering replacing this with
x = alpha \ averylongfunctionname(input1, input2, input3)
What is the best practice in this situation, from the standpoint of style and the standpoint of performance?
Here are some perplexing benchmarking results:
julia> using BenchmarkTools
[ Info: Precompiling BenchmarkTools [6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf]
julia> @btime x[1]\sum(x) setup=(x=rand(100))
15.014 ns (0 allocations: 0 bytes)
56.23358979466163
julia> @btime (1/x[1]) * sum(x) setup=(x=rand(100))
13.312 ns (0 allocations: 0 bytes)
257.4552413802698
julia> @btime sum(x)/x[1] setup=(x=rand(100))
14.929 ns (0 allocations: 0 bytes)
46.25209548841374
They are all about the same, but I'm surprised that the (1 / x) * foo
approach has the best performance.
Upvotes: 2
Views: 104
Reputation: 33249
Scalar /
and \
really should have the same meaning and performance. Let's define these two test functions:
f(a, b) = a / b
g(a, b) = b \ a
We can then see that they produce identical LLVM code:
julia> @code_llvm f(1.5, 2.5)
; @ REPL[29]:1 within `f'
define double @julia_f_380(double %0, double %1) {
top:
; ┌ @ float.jl:335 within `/'
%2 = fdiv double %0, %1
; └
ret double %2
}
julia> @code_llvm g(1.5, 2.5)
; @ REPL[30]:1 within `g'
define double @julia_g_382(double %0, double %1) {
top:
; ┌ @ operators.jl:579 within `\'
; │┌ @ float.jl:335 within `/'
%2 = fdiv double %0, %1
; └└
ret double %2
}
And the same machine code too. I'm not sure what is causing the differences in @btime
results, but I'm pretty sure that the difference between /
and \
is an illusion and not real.
As to x*(1/y)
, that does not compute the same thing as x/y
: it will be potentially less accurate since there is rounding done when computing 1/y
and then that rounded value is multiplied by x
, which also rounds. For example:
julia> 17/0.7
24.28571428571429
julia> 17*(1/0.7)
24.285714285714285
Since floating point division is guaranteed to be correctly rounded, doing division directly is always going to be more accurate. If the divisor is shared by a lot of loop iterations, however, you can get a speedup by rewriting the computation like this since floating-point multiplication is usually faster than division (although timing my current computer does not show this). Be aware that this comes at a loss of accuracy, however, and if the divisor is not shared there would still be a loss of accuracy and no performance gain.
Upvotes: 5
Reputation: 11
I don't know, but I can suggest you to try using BenchmarkTools package: it can help you to evaluate the performance of the two different statements. Here you can find more details. Bye!
I think that the best choice is (1/x)*foo
for two reasons:
Upvotes: 0