Max
Max

Reputation: 845

Using `\` instead of `/` in Julia

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

Answers (2)

StefanKarpinski
StefanKarpinski

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

arnestc
arnestc

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:

  1. it has the best performance (although not much compared to the other ones);
  2. it is more clear for another person reading the code.

Upvotes: 0

Related Questions