Mam dwa skrypty, z których każdy oblicza silnię liczby. Chciałbym wiedzieć, który jest szybszy. time
Komenda daje mi milisekund, a wynik jest różny od czasu do czasu:
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$
Jak poświęcić średni czas na uruchomienie skryptu? Mógłbym parsować i uśredniać wydajność 100 time
, ale wyobrażam sobie, że istnieje lepsze rozwiązanie?
Odpowiedzi:
Nie, twój pomysł na uśrednianie jest poprawny.
Wykonywanie skryptu zależy od wielu czynników, ale należy je rozdzielić na czas konfiguracji (ładowanie interpretera do pamięci, konfigurowanie i ewentualnie kompilowanie kodu do kodu bajtowego lub kodu maszynowego) i rzeczywisty czas wykonania.
Aby lepiej skoncentrować się na wewnętrznym czasie wykonywania, wykonujesz pętlę w samym skrypcie (tzn. Zamiast obliczać jedną silnię, obliczasz ją 100 razy w ramach jednego wykonania skryptu. Skrypt zostanie skonfigurowany raz, a wewnętrzna procedura wykona 100 czasy).
Aby skoncentrować się na czasie całkowitym, skrypt wykonuje się sto razy i uśrednia wyniki. Najlepiej jest rozdzielić te wykonania na tyle, aby system za każdym razem powracał w „stanie odniesienia” (lub stanie niezwiązanym ze skryptem). Na przykład sam interpreter zostanie zapisany w pamięci podręcznej, dzięki czemu pierwsze wykonanie skryptu będzie znacznie wolniejsze niż kolejne.
Aby uzyskać lepszy wgląd w algorytm, myślę, że najlepszym sposobem jest coś takiego (na innym komputerze bezczynnym):
Aplikacja działa tylko raz, cała konfiguracja i zalewanie jest wykonywane przez pierwszą nieterminową iterację, więc powinno to zminimalizować koszty ogólne (z wyjątkiem może połączenia czasowego).
Jeśli funkcja odbiera dane wejściowe, dobrze byłoby podać losową sekwencję danych wejściowych za pomocą PRNG z ustaloną wartością, aby zapewnić, że obie wersje testowanej funkcji otrzymają te same wartości. Dzięki temu jedna funkcja działa najwyraźniej lepiej ze względu na „szczęśliwe liczby” (np. Pamiętam odmianę algorytmu Hillsorta, która działała znacznie lepiej, jeśli liczba sortowanych elementów była w postaci 2 k -1 z małymi k s).
źródło
Możesz uruchamiać iteracje programu w pętli; i podziel całkowity czas przez liczbę iteracji:
źródło
{1..10}
i jestem zaskoczony, że to działa, nie mogę go znaleźć w podręczniku bash. Jedyną smutną rzeczą jest to, że nie znasz rozkładu swoich wyników (czas minimalny i maksymalny).man -P 'less +/Brace\ Expansion' bash
bash
. Spróbuj uruchomić/bin/bash
wcześniej.istnieje narzędzie o nazwie multitime, które dokładnie to robi: kilkukrotne uruchomienie polecenia, pomiar czasu potrzebnego (automatycznie / użytkownik / system ze automatycznie obliczonym średnim, min / maks. i medianą czasu)
Na przykład, aby zmierzyć podobny skrypt 100 razy:
źródło
To jest stare, ale pojawiło się tak wysoko w Google, gdy szukałem polecenia, którego użyłem wcześniej, ale nie mogłem znaleźć. W każdym razie mój preferowany sposób to:
Daje to sporo szczegółów, w tym średni czas wykonania na samym końcu:
źródło
Na
-n
,-r
i inne opcje zobacz https://docs.python.org/2/library/timeit.html#command-line-interfaceźródło
Hyperfine to kolejna opcja.
Przykładowe użycie:
źródło