У меня есть два сценария, каждый из которых вычисляет факториал числа. Я хотел бы знать, что быстрее. Команда time
дает мне миллисекунды, и время от времени результат отличается:
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.089s
user 0m0.052s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.091s
user 0m0.048s
sys 0m0.036s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.088s
user 0m0.048s
sys 0m0.040s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.088s
user 0m0.048s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.087s
user 0m0.064s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000
real 0m0.089s
user 0m0.068s
sys 0m0.016s
piousbox@piousbox-laptop:~/projects/trash$
Как мне взять среднее время, необходимое для запуска скрипта? Я мог бы проанализировать и усреднить результат 100 time
, но я думаю, что есть лучшее решение?
Ответы:
Нет, ваша идея усреднения верна.
Выполнение сценария зависит от множества факторов, и, тем не менее, оно должно быть разделено между временем установки (загрузка интерпретатора в память, настройка и, возможно, компиляция кода в байт-код или машинный код) и истинным временем выполнения.
Чтобы лучше сосредоточиться на внутреннем времени выполнения, вы выполняете цикл в самом скрипте (т.е. вместо вычисления одного факториала вы вычисляете его 100 раз за одно выполнение скрипта. Сценарий будет настроен один раз, а внутренняя подпрограмма выполнит 100 раз).
Чтобы сосредоточиться на общем времени, вы выполняете скрипт сто раз и усредняете результаты. В идеале, вы должны разделить эти исполнения настолько, чтобы система каждый раз возвращалась в «эталонное состояние» (или состояние, не связанное со сценарием). Например, сам интерпретатор будет кэшироваться в памяти, так что самое первое выполнение скрипта будет заметно медленнее, чем последующие.
Чтобы лучше понять алгоритм, я думаю, что лучший способ - это что-то вроде этого (на другом простаивающем компьютере):
Приложение запускается только один раз, все настройки и инициализация выполняются первой несвязанной итерацией, поэтому это должно минимизировать накладные расходы (за исключением, возможно, временного вызова).
Если функция получает входные данные, вы должны предоставить случайную последовательность входных данных, используя PRNG, засеянный с фиксированным значением, чтобы обе версии тестируемой функции получали одинаковые значения. Это позволяет избежать одной функции, выполняющей, по- видимому, лучше из-за «счастливых чисел» (например, я помню вариант алгоритма Хиллсорта, который работал заметно лучше, если число элементов, подлежащих сортировке, было в форме 2 k -1 с малыми k s).
источник
Вы можете запускать итерации программы в цикле; и разделите общее время на количество итераций:
источник
{1..10}
прежде, и сбит с толку, что это работает, не могу найти это в руководстве по bash. Печально только то, что вы не знаете, как распределяются ваши результаты (минимальное и максимальное время).man -P 'less +/Brace\ Expansion' bash
bash
. Попробуйте запустить/bin/bash
до этого.есть инструмент под названием multitime, который делает именно это: несколько раз запускает команду, измеряя, сколько времени это займет (реальное / пользователь / система с автоматически вычисленными средним, минимальным / максимальным и средним временем)
Например, для измерения аналогичного сценария 100 раз:
источник
Это старый, но он поднялся так высоко в Google, когда я искал команду, которую использовал ранее, но не смог найти. В любом случае, мой предпочтительный способ сделать это:
Это дает довольно много деталей, включая среднее время выполнения в конце:
источник
Для
-n
,-r
и других вариантов см https://docs.python.org/2/library/timeit.html#command-line-interfaceисточник
Hyperfine это еще один вариант.
Пример использования:
источник