Разница между benchmark и time macro В Юлия
недавно я обнаружил огромную разницу между двумя макросами: @benchmark и @time с точки зрения информации о распределении памяти и времени. Например:
@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)
почему существует большая разница между этими двумя примерами?
1 ответов
причина предварительной компиляции накладные. Чтобы увидеть это определение:
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
определяется заново с каждым вызовом и, следовательно, компиляция должна выполняться каждый раз.
и теперь решающее значение дело в том, что BenchmarkTools.jl обертывает ваш код в функцию, которую вы можете проверить, проверив, как generate_benchmark_definition
функция работает в этом пакете, поэтому она эквивалентна первому подходу, представленному выше.
другим способом запуска кода без переопределения оптимизированной функции будет:
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.дл я добавить его, чтобы показать, что при использовании функции g
вы не платите налог на предварительную компиляцию дважды)