Разница между эталоном и временем макроса в Юлии - PullRequest
0 голосов
/ 29 июня 2018

Недавно я обнаружил огромную разницу между двумя макросами: @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 Ответ

0 голосов
/ 29 июня 2018

Причина - накладные расходы на прекомпиляцию. Чтобы увидеть это определение:

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.jl - я добавляю его, чтобы показать, что при использовании функции g вы не платите налог на прекомпиляцию дважды)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...