在Julia中使用“而不是`/`

对于标量,(求解线性系统)运算符等效于除法运算符/。性能相似吗?

我问是因为目前我的代码有一行

x = (1 / alpha) * averylongfunctionname(input1, input2, input3)

从视觉上看,除法alpha发生在“左侧”很重要,所以我正在考虑将其替换为

x = alpha  averylongfunctionname(input1, input2, input3)

在这种情况下,从风格和性能的角度来看,最佳实践是什么?

以下是一些令人困惑的基准测试结果:

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

它们都差不多,但令我惊讶的是该(1 / x) * foo 方法具有最佳性能。

回答

标量/真正应该具有相同的含义和性能。让我们定义这两个测试函数:

f(a, b) = a / b
g(a, b) = b  a

然后我们可以看到它们生成了相同的 LLVM 代码:

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
}

而且机器码也是一样的。我不确定是什么导致了@btime结果的差异,但我很确定/和之间的差异是一种错觉而不是真实的。

至于x*(1/y),这不会计算与 相同的事情x/y:它可能不太准确,因为在计算时进行了舍入1/y,然后将舍入的值乘以x,这也舍入。例如:

julia> 17/0.7
24.28571428571429

julia> 17*(1/0.7)
24.285714285714285

由于浮点除法保证被正确舍入,直接除法总是会更准确。但是,如果除数由许多循环迭代共享,您可以通过像这样重写计算来获得加速,因为浮点乘法通常比除法快(尽管我当前的计算机没有显示这一点)。但是请注意,这会损失准确性,并且如果不共享除数,仍然会损失准确性并且不会提高性能。


以上是在Julia中使用“而不是`/`的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>