W jaki sposób mogę przetestować funkcję Julii?

11

tło

Sam nauczyłem się uczenia maszynowego i ostatnio zacząłem zagłębiać się w ekosystem uczenia maszynowego Julii.


Pochodząc z pythonowego środowiska i mając trochę doświadczenia z Tensorflow i OpenCV / skimage, chcę porównać biblioteki Julia ML (Flux / JuliaImages) z odpowiednikami, aby zobaczyć, jak szybko lub wolno wykonuje zadania CV (dowolne) i zdecydować, czy Powinienem przejść do korzystania z Julii.

Wiem, jak poświęcić czas na wykonanie funkcji w pythonie przy użyciu timeitmodułu takiego jak ten:

#Loading an Image using OpenCV

s = """\
img = cv2.imread('sample_image.png', 1)
"""
setup = """\
import timeit
"""
print(str(round((timeit.timeit(stmt = s, setup = setup, number = 1))*1000, 2)) + " ms")
#printing the time taken in ms rounded to 2 digits

Jak porównać czas wykonania funkcji wykonującej to samo zadanie w Julii przy użyciu odpowiedniej biblioteki (w tym przypadku JuliaImages).

Czy Julia udostępnia funkcję / makro do czasu / testu?

PseudoCodeNerd
źródło

Odpowiedzi:

10

using BenchmarkToolsjest zalecanym sposobem na przetestowanie funkcji Julii. Jeśli nie mierzysz czasu, co zajmuje sporo czasu, użyj jednego @benchmarklub mniej szczegółowych @btimemakr wyeksportowanych z niego. Ponieważ mechanizm stojący za tymi makrami wielokrotnie ocenia funkcję docelową, @timejest przydatny do testowania porównawczego rzeczy, które działają wolno (np. W przypadku dostępu do dysku lub bardzo czasochłonnych obliczeń).

Ważne jest, aby używać @btimelub @benchmarkpoprawnie, aby uniknąć wprowadzających w błąd wyników. Zwykle testujesz funkcję, która przyjmuje jeden lub więcej argumentów. Podczas testowania wszystkie argumenty powinny być zmiennymi zewnętrznymi: (bez makra testu porównawczego)

x = 1
f(x)
# do not use f(1)

Funkcja będzie oceniana wiele razy. Aby zapobiec ponownej ocenie argumentów funkcji za każdym razem, gdy funkcja jest oceniana, musimy oznaczyć każdy argument, poprzedzając a $nazwą każdej zmiennej używanej jako argument. Makra analizy porównawczej używają tego, aby wskazać, że zmienna powinna zostać oceniona (rozwiązana) jeden raz, na początku procesu analizy porównawczej, a następnie wynik należy ponownie wykorzystać bezpośrednio w następujący sposób:

julia> using BenchmarkTools
julia> a = 1/2;
julia> b = 1/4;
julia> c = 1/8;
julia> a, b, c
(0.5, 0.25, 0.125)

julia> function sum_cosines(x, y, z)
         return cos(x) + cos(y) + cos(z)
       end;

julia> @btime sum_cosines($a, $b, $c);  # the `;` suppresses printing the returned value
  11.899 ns (0 allocations: 0 bytes)    # calling the function takes ~12 ns (nanoseconds)
                                        # the function does not allocate any memory
# if we omit the '$', what we see is misleading
julia> @btime sum_cosines(a, b, c);    # the function appears more than twice slower 
 28.441 ns (1 allocation: 16 bytes)    # the function appears to be allocating memory
# @benchmark can be used the same way that @btime is used
julia> @benchmark sum_cosines($a,$b,$c) # do not use a ';' here
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     12.111 ns (0.00% GC)
  median time:      12.213 ns (0.00% GC)
  mean time:        12.500 ns (0.00% GC)
  maximum time:     39.741 ns (0.00% GC)
  --------------
  samples:          1500
  evals/sample:     999

Chociaż istnieją parametry, które można dostosować, wartości domyślne zwykle działają dobrze. Aby uzyskać dodatkowe informacje o BenchmarkTools dla doświadczonych użytkowników, patrz instrukcja .

Jeffrey Sarnoff
źródło
7

Julia udostępnia dwa makra dla środowiska wykonawczego kodu czasowego / testu porównawczego. To są :

  • @czas
  • @benchmark : zewnętrzny, zainstaluj przezPkg.add("BenchmarkTools")

Korzystanie z BenchmarkTools @benchmark jest bardzo łatwe i byłoby pomocne w porównaniu prędkości dwóch języków. Przykład użycia @bencharkprzeciwko podanej ławce pytona.

using Images, FileIO, BenchmarkTools

@benchmark img = load("sample_image.png")

Wynik :

BenchmarkTools.Trial: 
  memory estimate:  3.39 MiB
  allocs estimate:  322
  --------------
  minimum time:     76.631 ms (0.00% GC)
  median time:      105.579 ms (0.00% GC)
  mean time:        110.319 ms (0.41% GC)
  maximum time:     209.470 ms (0.00% GC)
  --------------
  samples:          46
  evals/sample:     1

Teraz, aby porównać średni czas, powinieneś wpisać samples(46) jako liczbę w kodzie Python timeit i podzielić go przez tę samą liczbę, aby uzyskać średni czas wykonania.

print(str(round((timeit.timeit(stmt = s, setup = setup, number = 46)/46)*1000, 2)) + " ms")

Możesz śledzić ten proces w celu porównywania dowolnej funkcji w Julii i Pythonie. Mam nadzieję, że twoje wątpliwości zostały wyjaśnione.


Uwaga : Z statystycznego punktu widzenia @benchmark jest znacznie lepszy niż @time.

PseudoCodeNerd
źródło
2
Należy pamiętać, że hałas związany z czasem jest w większości pozytywny, co oznacza, że ​​minimalny czas jest często (nie zawsze) bardziej pouczający. @btimei @belapsedzwróć tylko minimalny czas.
Fredrik Bagge