何时插入基准表达式

Cam*_*nek 5 julia

BenchmarkTools文档建议插值全局变量为基准的表达式。然而,他们提供的示例的运行时间差距似乎已经大大缩小。在他们的榜样,他们有一个全局变量A = rand(1000),他们比较@benchmark [i*i for i in A]@benchmark [i*i for i in $A],并获得13.806 ?s1.348 ?s分别。但是,当我现在运行该示例时,运行时间非常接近:

julia> using Statistics, BenchmarkTools

julia> A = rand(1000);

julia> median(@benchmark [i*i for i in A])
BenchmarkTools.TrialEstimate: 
  time:             892.821 ns
  gctime:           0.000 ns (0.00%)
  memory:           7.95 KiB
  allocs:           2

julia> median(@benchmark [i*i for i in $A])
BenchmarkTools.TrialEstimate: 
  time:             836.075 ns
  gctime:           0.000 ns (0.00%)
  memory:           7.95 KiB
  allocs:           2
Run Code Online (Sandbox Code Playgroud)

这是我的版本信息:

julia> versioninfo()
Julia Version 1.1.1
Commit 55e36cc (2019-05-16 04:10 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin15.6.0)
  CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Run Code Online (Sandbox Code Playgroud)

仍然需要在基准测试中进行插值吗?知道为什么现在运行时间如此相似吗?任何人都可以提供一个不同的示例,其中运行时间的不同程度远大于 1?

Mat*_* B. 7

BenchmarkTools 正在与编译器进行军备竞赛——在多个方面!

两个表达式的区别就相当于这两个函数的区别:

# @benchmark [i*i for i in A]
f1() = [i*i for i in A]

# @benchmark [i*i for i in $A]
f2(X) = [i*i for i in X]
Run Code Online (Sandbox Code Playgroud)

换句话说,使用 a$将值视为参数而不是硬编码的常量或全局变量。由于A是全局但不是常量,因此f1()类型不稳定的。当然,Julia 在处理类型不稳定性方面做得越来越好,而且似乎这是您不再为此付出代价的另一个地方。

有时,不使用 a$实际上会给出令人难以置信的快速结果,因为 Julia 会对值进行硬编码,并且可能会进行某种过度专门针对您正在基准测试的确切值的常量传播。这是一个显示两个方向的示例

julia> x = 0.5; # non-constant global

julia> @btime sin(x);
  20.106 ns (1 allocation: 16 bytes)

julia> @btime sin($x);
  5.413 ns (0 allocations: 0 bytes)

julia> @btime sin(0.5); # constant literal!
  1.818 ns (0 allocations: 0 bytes)

julia> @btime sin($0.5);
  5.416 ns (0 allocations: 0 bytes)
Run Code Online (Sandbox Code Playgroud)