Julia中基准和时间宏之间的区别 [英] Difference between benchmark and time macro in Julia
问题描述
我最近发现了两个宏之间的巨大差异:@benchmark 和@time 在内存分配信息和时间方面.例如:
I've recently discovered a huge difference between two macros: @benchmark and @time in terms of memory allocation information and time. For example:
@benchmark quadgk(x -> x, 0., 1.)
BenchmarkTools.Trial:
memory estimate: 560 bytes
allocs estimate: 17
--------------
minimum time: 575.890 ns (0.00% GC)
median time: 595.049 ns (0.00% GC)
mean time: 787.248 ns (22.15% GC)
maximum time: 41.578 μs (97.60% GC)
--------------
samples: 10000
evals/sample: 182
@time quadgk(x -> x, 0., 1.)
0.234635 seconds (175.02 k allocations: 9.000 MiB)
(0.5, 0.0)
为什么这两个例子有很大的不同?
Why there is a big difference between these two examples?
推荐答案
原因是预编译开销.要查看此定义:
The reason is precompilation overhead. To see this define:
julia> h() = quadgk(x -> x, 0., 1.)
h (generic function with 1 method)
julia> @time h()
1.151921 seconds (915.60 k allocations: 48.166 MiB, 1.64% gc time)
(0.5, 0.0)
julia> @time h()
0.000013 seconds (21 allocations: 720 bytes)
(0.5, 0.0)
相对于
julia> @time quadgk(x -> x, 0., 1.)
0.312454 seconds (217.94 k allocations: 11.158 MiB, 2.37% gc time)
(0.5, 0.0)
julia> @time quadgk(x -> x, 0., 1.)
0.279686 seconds (180.17 k allocations: 9.234 MiB)
(0.5, 0.0)
这里发生的情况是,在第一次调用中,将 quadgk
包装在一个函数中,匿名函数 x->x
只定义一次,因为它被包装在一个函数,因此 quadgk
只编译一次.在第二次调用中,每次调用都会重新定义 x->x
,因此每次都必须执行编译.
What happens here is that in the first call, wrapping quadgk
in a function, anonymous function x->x
is defined only once, since it is wrapped in a function, and thus quadgk
is compiled only once. In the second call x->x
is defined anew with every call and thus compilation has to be performed each time.
现在关键是 BenchmarkTools.jl 将您的代码包装在一个函数中,您可以通过检查 generate_benchmark_definition
函数在该包中的工作方式来检查该函数,因此它等效于上面介绍的第一种方法.
And now the crucial point is that BenchmarkTools.jl wraps your code in a function which you can check by inspecting how generate_benchmark_definition
function works in this package, so it is equivalent to the first approach presented above.
在不重新定义优化函数的情况下运行代码的另一种方法是:
Another way to run the code without redefining the optimized function would be:
julia> g(x) = x
g (generic function with 1 method)
julia> @time quadgk(g, 0., 1.)
1.184723 seconds (951.18 k allocations: 49.977 MiB, 1.58% gc time)
(0.5, 0.0)
julia> @time quadgk(g, 0., 1.)
0.000020 seconds (23 allocations: 752 bytes)
(0.5, 0.0)
(虽然这不是 BenchmarkTools.jl 所做的——我添加它是为了表明当您使用函数 g
时,您无需支付两次预编译税)
(though this is not what BenchmarkTools.jl does - I add it to show that when you use function g
you do not pay precompilation tax twice)
这篇关于Julia中基准和时间宏之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!