5

I rozwinęły kod, który otrzymuje na wejściu do dużego 2 trójwymiarowy obraz (do 64MPixels) oraz:Interpretacja wyjściu perf stat

  • Stosuje filtrów dla każdego rzędu
  • transponuje obrazu (stosowany blokowanie uniknąć wiele pomyłek cache)
  • stosuje filtry na kolumnach (obecnie rzędami) obrazu
  • transponuje przefiltrowany obraz z powrotem na prowadzenie z innymi obliczeniami

Mimo że nic nie zmienia, to ze względu na kompletność mojego pytania, filtrowanie polega na zastosowaniu dyskretnej transformacji falkowej, a kod jest zapisany w C.

Moim celem końcowym jest sprawienie, aby ten przebieg był tak szybki jak możliwy. Przyspieszenia, które do tej pory miałem ponad 10 razy, dzięki transpozycji matrycy blokującej, wektoryzacji, wielowątkowości, kodowi kompilatorowi itd.

Przechodząc do mojego pytania: Najnowsze statystyki profilowania kodu, które mam (przy użyciu perf stat -e) niepokoiły mnie.

 76,321,873 cache-references            
    8,647,026,694 cycles     # 0.000 GHz      
    7,050,257,995 instructions    # 0.82 insns per cycle   
     49,739,417 cache-misses    # 65.171 % of all cache refs  

     0.910437338 seconds time elapsed 

(Liczba błędów pamięci podręcznej)/(instrukcje #) jest niska około ~ 0,7%. Here Wspomniano, że ta liczba to dobra rzecz, o której należy pamiętać, aby sprawdzić wydajność pamięci.

Z drugiej strony% pamięci podręcznej - pomijany w odniesieniach do pamięci podręcznej jest znacząco wysoki (65%!), Co jak widzę może świadczyć o tym, że coś jest nie tak z wykonaniem pod względem wydajności pamięci podręcznej.

Szczegółowy stat z perf stat -d jest:

2711.191150 task-clock    # 2.978 CPUs utilized   
     1,421 context-switches   # 0.524 K/sec     
      50 cpu-migrations   # 0.018 K/sec     
     362,533 page-faults    # 0.134 M/sec     
8,518,897,738 cycles     # 3.142 GHz      [40.13%] 
6,089,067,266 stalled-cycles-frontend # 71.48% frontend cycles idle [39.76%] 
4,419,565,197 stalled-cycles-backend # 51.88% backend cycles idle [39.37%] 
7,095,514,317 instructions    # 0.83 insns per cycle   
             # 0.86 stalled cycles per insn [49.66%] 
    858,812,708 branches     # 316.766 M/sec     [49.77%] 
    3,282,725 branch-misses    # 0.38% of all branches   [50.19%] 
1,899,797,603 L1-dcache-loads   # 700.724 M/sec     [50.66%] 
    153,927,756 L1-dcache-load-misses  # 8.10% of all L1-dcache hits [50.94%] 
    45,287,408 LLC-loads     # 16.704 M/sec     [40.70%] 
    26,011,069 LLC-load-misses   # 57.44% of all LL-cache hits [40.45%] 

    0.910380914 seconds time elapsed 

Tutaj cykle interfejsu internetowego i backend utknęły są również wysokie i pamięci podręczne niższego poziomu wydaje się cierpieć z powodu wysokiego wskaźnika Miss 57,5%.

Który wskaźnik jest najbardziej odpowiedni dla tego scenariusza? Pomyślałem, że może się zdarzyć, że obciążenie nie będzie wymagało dalszego "dotykania" pamięci podręcznych LL po początkowym załadowaniu obrazu (ładowanie wartości raz i później) - obciążenie jest bardziej obciążone przez procesor niż związany z pamięcią algorytm filtrowania obrazu).

Maszyna, na której to działa, to Xeon E5-2680 (20M inteligentnego bufora podręcznego, z czego 256 kB L2 cache na rdzeń, 8 rdzeni).

+0

koukouviou, 'perf stat -d' może być niedokładne, może być użyteczne powtórzenie go kilka razy przy 4-5 zdarzeniach na przebieg,' perf stat-L1-dcache-ładunki, L1-dcache-load-missses , LLC-ładuje, LLC-ładuje-omija ". Jeśli twoje etapy mogą być rozdzielone, możesz zmierzyć każdy etap, aby znaleźć, które generuje chybienia. Lub możesz uruchomić 'perf record -e cache-missses', aby uzyskać profil kodu, który ma najwięcej pomyłek (jak było zalecane w [" Tutaj "] (http://developerblog.redhat.com/2014/03/10/ określanie-czy-aplikacja-ma-słabe-cache-wydajność-2 /), które łączyłeś). – osgx

+0

@osgx Zrobiłem testy, o których wspomniałeś, ale post był już długi, więc zachowałem go tak krótko, jak tylko mogłem. Chociaż statystyki nieco się zmieniają, pozostają statystycznie podobne w przypadku dużych błędów pamięci podręcznej%. Uruchomiłem perf/report/annotate, a pomyłki są przypisywane w dużej mierze do kernel-kallsyms, ale nie wiem co z tym zrobić ... – koukouviou

+0

koukouviou, Możesz ponownie uruchomić statystyki ze wszystkimi zdarzeniami ograniczonymi do użytkownika- space: 'perf stat -e event1: u, event2: u, ...' i porównaj z opublikowanymi wynikami (domyślnie mierzony jest zarówno użytkownik, jak i jądro). kernel-kallsyms oznacza, że ​​niektóre funkcje z przestrzeni jądra miały to wydarzenie ... Niektóre możliwe problemy nieznanych/nierozwiązanych symboli są wymienione tutaj: http://www.brendangregg.com/blog/2014-06-22/perf-cpu -sample.html. Nie mogę udzielić ci rad na temat pomiarów ... – osgx

Odpowiedz

3

Pierwszą rzeczą, którą chcesz się upewnić, że nikt inny obliczyć intensywny proces jest uruchomiony na komputerze. To jest procesor serwera, więc pomyślałem, że to może być problem.

Jeśli używasz wielowątkowości w swoim programie i dystrybuujesz równą ilość pracy między wątkami, możesz być zainteresowany zebranie danych tylko na jednym procesorze.

Proponuję wyłączenie hiper-wątku w fazie optymalizacji, ponieważ może to prowadzić do nieporozumień podczas interpretowania metryk profilowania. (np. zwiększenie liczby cykli spędzonych w zapleczu). Również jeśli rozprowadzasz pracę do 3 wątków, masz dużą szansę, że 2 wątki będą dzielić zasoby jednego rdzenia, a trzeci będzie miał dla siebie cały rdzeń - i będzie szybszy.

Perf nigdy nie był zbyt dobry w wyjaśnianiu wskaźników. Sądząc po rzędzie wielkości, odniesienia do pamięci podręcznej są błędami L2, które uderzyły w LLC. Wysoka liczba miss LLC w porównaniu z referencjami LLC nie zawsze jest zła, jeśli liczba referencji LLC/#Instructions jest niska. W twoim przypadku masz 0.018, więc oznacza to, że większość twoich danych jest używana z L2. Wysoki współczynnik miss LLC oznacza, że ​​nadal musisz pobrać dane z pamięci RAM i je zapisać.

Odnośnie #Cycles BE i FE, jestem trochę zaniepokojony tymi wartościami, ponieważ nie sumują się one do 100% i do całkowitej liczby cykli. Masz 8G, ale pozostajesz 6G w cyklach FE i 4G w BE. To nie wydaje się bardzo poprawne.

Jeśli cykle FE są wysokie, oznacza to, że brakuje ci pamięci podręcznej instrukcji lub spekulacji w złych gałęziach. Jeśli cykle BE są wysokie, oznacza to, że czekasz na dane.

W każdym razie, jeśli chodzi o twoje pytanie. Najodpowiedniejszym sposobem oceny wydajności twojego kodu jest Instrukcje/Cycle (IPC). Twój procesor może wykonać do 4 instrukcji/cyklu. Wykonujesz tylko 0,8. Oznacza to, że zasoby są niedostatecznie wykorzystane, z wyjątkiem przypadku, gdy masz wiele instrukcji wektorowych. Po IPC musisz sprawdzić, czy nie ma luki w gałęziach i L1 (dane i kod), ponieważ generują one najwięcej kar.

Ostatnia sugestia: może zainteresować Cię wzmacniacz VTune firmy Intel. Daje znacznie lepsze wyjaśnienie metryk i wskazuje na ewentualne problemy w kodzie.

+1

Stojaki VAndrei, BE i FE nigdy nie sumują się z instrukcjami do 100% cykli, ponieważ większość procesorów Intela jest superpodpływowych. Wiele instrukcji może być uruchomionych w locie, a niektóre generują stalle; ale niektóre zostaną wykonane. Stojaki FE z 71% są wysokie (masz dużo kodu, który jest skomplikowany do rozszyfrowania?) I 51% stoisk BE jest dość wysokie - więc istnieje kilka problemów ... koukouviou, możesz również wypróbować 'toplev.py' od [andikleen/pmu-tools (github)] (https://github.com/andikleen/pmu-tools) jako bezpłatny środek zaradczy dla Vtune. – osgx

+0

koukouviou, opis 'toplev.py' od autora - http://halobates.de/blog/p/262 – osgx

+0

@osgx. Nie jestem tego taki pewien. Wiązanie FE oznacza, że ​​jednostka rezerwacji nie jest zasilana instrukcjami, więc nie ma zadań do wykonania. Wynika to z chybienia pamięci podręcznej kodu, złożonych instrukcji i złych spekulacji. Jeśli BE jest wysokie, oznacza to, że instrukcje utrzymują porty wykonawcze zajęte, ale czekają na zasoby (dane lub darmowe rejestry) lub mają duże opóźnienia (np. Transcedentale). Powinna być inna metryka: #cycles wycofująca się. Jeśli spojrzysz na vTune, zobaczysz, że FE + BE + Retiring dodają do 100% zawsze. – VAndrei