Jak zmierzyć średni czas wykonania skryptu?

23

Mam dwa skrypty, z których każdy oblicza silnię liczby. Chciałbym wiedzieć, który jest szybszy. timeKomenda 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?

Victor Piousbox
źródło
1
stackoverflow.com/questions/8215482/...
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件 事件

Odpowiedzi:

4

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):

  • zawiń algorytm w jedną funkcję.
  • w aplikacji kontrolującej:
    • wywołaj funkcję raz
    • uzyskaj czas systemowy („zegar ścienny”) i dodaj 10 (lub rozsądną N) sekund
    • wejdź do pętli i zacznij odliczać iteracje
    • po każdym wywołaniu funkcji zwiększ licznik
    • jeśli czas systemowy jest niższy niż czas zaoszczędzony, wykonaj kolejną pętlę
    • uzyskaj dokładną N, być może zmiennoprzecinkową, z bieżącego czasu zegara ściennego
    • wyświetl licznik podzielony przez N: liczba iteracji na sekundę.

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).

LSerni
źródło
Racja, dzięki. Zauważyłem, że kolejne połączenia były coraz krótsze. Teraz uruchamiam pętlę w skryptach i stwierdziłem, że jeden algorytm jest zdecydowanie szybszy od drugiego.
Victor Piousbox,
39

Możesz uruchamiać iteracje programu w pętli; i podziel całkowity czas przez liczbę iteracji:

time for i in {1..10}; do sleep 1; done
real    0m10.052s
user    0m0.005s
sys 0m0.018s
Kent
źródło
2
Bardzo proste, uwielbiam to. Nigdy też nie widziałem {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).
w00t
@ w00t:man -P 'less +/Brace\ Expansion' bash
user2683246 10.0915
Dzięki @ user2683246! Znalazłem go również na gnu.org/software/bash/manual/bash.html#Brace-Expansion - fajne wykorzystanie mniej btw. Teraz jestem również ciekawy, kiedy pojawiło się to w bash…
w00t
1
Aha, wersja 3, 10 lat po tym, jak zacząłem używać bash :) tldp.org/LDP/abs/html/bashver3.html
w00t
2
Jeśli to nie działa dla przybywających pracowników Google, może to oznaczać, że nie biegasz bash. Spróbuj uruchomić /bin/bashwcześniej.
Cory Klein
14

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:

multitime -q -n 100 "fact1.sh"
===> multitime results
1: -q fact1.sh
            Mean        Std.Dev.    Min         Median      Max
real        0.122       0.032       0.086       0.116       0.171       
user        0.148       0.044       0.096       0.137       0.223       
sys         0.023       0.019       0.000       0.014       0.061 
Cyryl Chaboisseau
źródło
12

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:

perf stat -r 10 -B sleep 1

Daje to sporo szczegółów, w tym średni czas wykonania na samym końcu:

1.002248382 seconds time elapsed                   ( +-  0.01% )
Zaahid
źródło
1

Hyperfine to kolejna opcja.

Przykładowe użycie:

hyperfine --warmup 3 'ruby fac1.rb'
Luís Bianchin
źródło
1
hyperfine jest o wiele lepsza niż inne alternatywy, że jest śmieszna. Konieczne wykrycie przebiegów, rozgrzewka, piękne wyniki, raporty przeceny, napisane w
rdzeniu