Czy analiza algorytmiczna polegająca na liczeniu flopów jest przestarzała?


43

Na moich kursach analizy numerycznej nauczyłem się analizować wydajność algorytmów, licząc liczbę wymaganych operacji zmiennoprzecinkowych (klap) w stosunku do wielkości problemu. Na przykład w tekście Trefethen & Bau na temat numerycznej algebry liniowej są nawet trójwymiarowe zdjęcia liczby flopów.

Teraz modne jest stwierdzenie, że „flopy są bezpłatne”, ponieważ opóźnienie pamięci do pobrania czegokolwiek poza pamięcią podręczną jest o wiele większe niż koszt flopa. Ale nadal uczymy studentów, jak liczyć klapy, przynajmniej na kursach analizy numerycznej. Czy zamiast tego powinniśmy ich uczyć liczenia dostępów do pamięci? Czy musimy pisać nowe podręczniki? A może dostęp do pamięci jest zbyt specyficzny dla urządzenia, aby spędzać czas? Jaki będzie długoterminowy trend, jeśli chodzi o to, czy wąskie gardło ma dostęp do klap lub pamięci?

Uwaga: niektóre z poniższych odpowiedzi wydają się odpowiadać na inne pytanie, takie jak „Czy mam obsesyjnie przepisać moją implementację, aby zaoszczędzić kilka flopów lub poprawić wydajność pamięci podręcznej?” Ale pytam bardziej w stylu: „ Czy bardziej przydatne jest oszacowanie złożoności algorytmicznej pod względem operacji arytmetycznych lub dostępu do pamięci ?”


1
> „Czy bardziej przydatne jest oszacowanie złożoności algorytmicznej pod względem operacji arytmetycznych lub dostępu do pamięci?” . Z praktycznego punktu widzenia systemy osadzone są nadal ograniczone szybkością FPU, a nie przepustowością pamięci. Tak więc, nawet jeśli liczenie flopów zostało uznane za przestarzałe ze względu na standardy HPC, nadal ma praktyczne zastosowanie dla innych społeczności.
Damien

Odpowiedzi:


31

Myślę, że właściwą rzeczą (pierwsze zamówienie) jest przyjrzenie się stosunkowi flopów do bajtów potrzebnych w algorytmie, który nazywam . Niech będzie maksymalną szybkością flopa procesora, a maksymalną przepustowością. Jeśli , wówczas algorytm będzie ograniczony. Jeśli , algorytm jest ograniczony do flopa.F m a x B m a xβFmaxBmaxBmaxβ>FmaxFmaxβ>BmaxBmaxβ>Fmax

Myślę, że liczenie dostępu do pamięci jest obowiązkowe, ale powinniśmy również pomyśleć o:

  • Ile pamięci lokalnej jest wymagane

  • Ile mamy możliwych współbieżności

Następnie możesz zacząć analizować algorytmy dla nowoczesnego sprzętu.


3
Zgadzam się z Mattem, ale chcę zauważyć, że jest obecnie dość powszechnie określany w literaturze jako „intensywność arytmetyczna” i „intensywność liczbowa”. Myślę, że model Roofline autorstwa Williamsa, Watermana i Pattersona jest prawdopodobnie dobrym początkiem do myślenia o tych problemach. Myślę, że powinno to zostać rozszerzone na stosunek pamięci / flopa algorytmu w czasie. β
Aron Ahmadia

2
David robi więcej 8 lat wcześniej.
Matt Knepley,

3
Okej, więc istnieje lepszy, bardziej złożony model (jak zawsze). Ale ten model daje odpowiedź zależną od maszyny. Czego powinniśmy nauczyć uczniów, aby używać ich jako pierwszej analizy?
David Ketcheson,

3
Chodzi o to, że maszyna została zredukowana do jednej liczby, czyli stosunku pików szczytowych do szczytowej przepustowości, podobnie jak algorytm. To jest tak proste, jak to możliwe. Bez modelu obliczeniowego jakiekolwiek oszacowanie złożoności jest bezużyteczne i jest to najprostsze realistyczne.
Matt Knepley,

1
Myślę, że źle zrozumiałeś problem. Mamy już transport optyczny, który może przenosić duże ładunki. Problem polega na tym, że jest to chip. Masz tylko tyle przewodów i najwyższą częstotliwość zegara. Transport optyczny złagodziłby ten problem jedynie w układzie optycznym.
Matt Knepley,

22

Nie rozumiem, dlaczego trzeba być „zwycięzcą”; nie jest to gra o sumie zerowej, w której liczy się flop, a dostęp do pamięci musi zagłuszyć drugą. Możesz uczyć ich obu i myślę, że oboje mają swoje zastosowania. W końcu trudno powiedzieć, że twój algorytm z dostępem do pamięci pewnością będzie szybszy niż twój algorytm z dostępem . Wszystko zależy od względnych kosztów różnych części (tego nieznośnego czynnika, który zawsze ignorujemy w tych analizach!).O ( N ) O ( N log N ) O ( N 2 )O(N4)O(N)O(NlogN)O(N2)

Z szerszej perspektywy uważam, że analiza wydajności algorytmu powinna być „kompleksowa”. Jeśli uczymy ludzi prawdziwych programistów i użytkowników HPC, muszą oni zrozumieć, jakie są koszty programowania w prawdziwym świecie. Modele analizy abstrakcyjnej, które nie uwzględniają czasu programisty. Powinniśmy myśleć w kategoriach „całkowitego czasu do rozwiązania”, a nie tylko liczby flopów i wydajności algorytmicznej. Nie ma sensu spędzać trzech lub czterech dni programisty na przepisaniu procedury, która pozwoli zaoszczędzić jedną sekundę czasu komputerowego na zadanie, chyba że planujesz przeprowadzić kilka milionów obliczeń. Podobnie, kilkudniowa inwestycja pozwalająca zaoszczędzić godzinę lub dwie godziny obliczeń szybko się zwraca. Ten nowatorski algorytm może być niesamowity,


7
Algorytm wykonuje dostępu do danych? :)O ( N 2 )O(NlogN)O(N2)
Andreas Klöckner

2
Dlaczego nie? Jeśli odnosi się tylko do operacji zmiennoprzecinkowych, być może istnieje także znaczna liczba operacji całkowitych, które powodują dostęp do danych :)O ( N 2 )O(NlogN)O(N2)
kini

9

Jak zauważyli inni, odpowiedź zależy oczywiście od tego, czy wąskim gardłem jest przepustowość procesora czy pamięci. W przypadku wielu algorytmów, które działają na dowolnym zestawie danych o dowolnym rozmiarze, wąskim gardłem jest zwykle przepustowość pamięci, ponieważ zestaw danych nie mieści się w pamięci podręcznej procesora.

Co więcej, Knuth wspomina, że ​​analiza dostępu do pamięci prawdopodobnie wytrzyma próbę czasu, prawdopodobnie dlatego, że jest stosunkowo prosta (nawet biorąc pod uwagę łatwość buforowania) w porównaniu ze złożonością współczesnych potoków procesora i prognozowaniem rozgałęzień.

Knuth używa terminu gigamems w tomie 4A TAOCP podczas analizy BDD. Nie jestem pewien, czy używa go w poprzednich tomach. Wspomniał o tym, jak wytrzymać próbę czasu, podczas corocznego wykładu na temat choinki w 2010 roku.

Co ciekawe, robisz to źle Źle pokazuje, że nawet analizowanie wydajności w oparciu o operacje pamięci nie zawsze jest proste, ponieważ istnieją elementy, takie jak nacisk VM, które wchodzą w grę, jeśli dane nie mieszczą się jednocześnie w fizycznej pamięci RAM.


8

To, jak określisz koszty algorytmu, zależy od tego, na jakim „poziomie” obliczeń naukowych pracujesz i od (wąskiej lub szerokiej) klasy problemów, które rozważasz.

Jeśli zastanawiasz się nad optymalizacją pamięci podręcznej, jest to wyraźnie bardziej odpowiednie np. Dla implementacji numerycznych pakietów algebry liniowej, takich jak BLAS i podobne biblioteki. Należy to do optymalizacji niskiego poziomu i jest w porządku, jeśli masz ustalony algorytm dla konkretnego problemu i wystarczające ograniczenia na wejściu. Na przykład optymalizacja pamięci podręcznej może być istotna, aby uzyskać szybką implementację sprzężonej iteracji gradientu, jeśli obiecuje się, że macierz będzie wystarczająco rzadka.

Z drugiej strony, im szersza klasa problemów, tym mniej można przewidzieć na podstawie rzeczywistych obliczeń (np. Nie wiesz, jak bardzo rzadkie będą macierze wejściowe implementacji CG). Im szersza klasa maszyn, na których program ma działać, tym mniej można przewidzieć na architekturze pamięci podręcznej.

Ponadto, na wyższym poziomie informatyki naukowej, bardziej odpowiednia może być zmiana struktury problemu. Na przykład, jeśli poświęcasz czas na znalezienie dobrego warunku wstępnego dla liniowego układu równań, ten rodzaj optymalizacji zwykle przewyższa jakąkolwiek optymalizację niskiego poziomu, ponieważ liczba iteracji jest drastycznie zmniejszona.

Podsumowując, optymalizacja pamięci podręcznej jest użyteczna tylko wtedy, gdy nie ma już nic do optymalizacji przez równoległość i redukcję asymptotycznej liczby FLOP.

Myślę, że rozsądnie jest dostosować stanowisko informatyki teoretycznej: w końcu poprawa asymptotycznej złożoności algorytmu ma większy zwrot niż mikrooptymalizacja niektórych istniejących linii kodu. Dlatego zliczanie FLOP jest nadal preferowane.


„Optymalizacja pamięci podręcznej jest przydatna tylko wtedy, gdy nie ma już nic do optymalizacji przez równoległość i redukcję asymptotycznej liczby FLOP”. Nie zgadzam się. Jeśli chcesz obliczyć duże wyrażenie dużej liczby liczb, lepiej wykonać jeden krok na raz ze wszystkimi liczbami niż wszystkie kroki dla każdej liczby. Oba mają tę samą liczbę FLOPS, ale jeden jest lepszy w dostępie do pamięci. Bonus, jeśli wybierzesz rozmiar paczki, aby zmieścił się w pamięci podręcznej (lub kompilator zrobi to za Ciebie). Oto, co robi numexpr w Pythonie: github.com/pydata/numexpr
Davidmh

6

Zawsze nie chciałem nawet myśleć o liczeniu klap, dostępach do pamięci czy cokolwiek innego. To koncepcja z lat 60. XX wieku, kiedy to, co zrobiłeś, było właściwie dane i tylko od tego, jak to zrobiłaś, zależało od optymalizacji algorytmicznej. Zastanów się nad rozwiązaniem problemu elementu skończonego na jednolitej siatce xyz, stosując albo Gaussowską eliminację iteracji Jacobiego.

Teraz możesz zoptymalizować to do piekła i zaoszczędzić kilka flopów, zyskując 10% czasu działania. Możesz też pomyśleć o wdrożeniu metody wielosieciowej i optymalnego warunku wstępnego bloku, uzyskując współczynnik 10 w czasie wykonywania. Do tego powinniśmy szkolić naszych uczniów - zastanów się, jakie złożone zewnętrzne algorytmy mogą cię zyskać, próbując znaleźć lepszy wewnętrzny algorytm. Twój szef (Keyes) ma te slajdy na temat postępów w obliczeniach MHD, które sprawiają, że ten punkt jest dość oczywisty.


Właściwie pytałem o rodzaj myślenia na wysokim poziomie, który sugerujesz, a nie o optymalizację na niskim poziomie. Jakich wskaźników należy użyć, aby ustalić, czy multigrid i Twój kondycjoner będą szybsze niż alternatywy?
David Ketcheson

Nie wiedziałbym, jak liczyć ręcznie - FLOPS lub jakiekolwiek inne instrukcje liczą złożone algorytmy, które działają na dziesiątkach lub tysiącach wierszy kodu. Pomyśl na przykład, jak złożona jest analiza i konstrukcja algorytmów AMG. Jest tak wiele części tych algorytmów i wszystkie one zależą od rzeczywistych danych, że nie można przewidzieć liczby operacji.
Wolfgang Bangerth,

1
Myślę, że na początku źle zrozumiałem, do czego zmierzasz, ale nadal nie zgadzam się z twoją tezą. „Zewnętrzne algorytmy” można (i powiedziałbym, należy) nadal projektować z myślą o asymptotycznej złożoności. Na pewno nie twierdziłbyś, że spadek z algorytmu kwadratowego do algorytmu prawie liniowego w najlepszym wypadku doprowadziłby do 10% skrócenia czasu działania; ale jak inaczej obliczyć asymptotyczną złożoność niż za pomocą klap i / lub operacji pamięci?
Jack Poulson,

7
Myślę, że to podejście do algorytmów „podnieś ręce” to bzdura. Musisz uprościć analizę, patrząc tylko na koszty pierwszego rzędu i upraszczając model, aby był wykonalny, ale stwierdzenie, że nie możesz analizować czegoś takiego jak MG lub Cholesky, ponieważ jest zbyt skomplikowane, jest całkowicie błędne.
Matt Knepley,

1
Cóż, ale co to znaczy analizować MG lub Cholesky'ego, gdy każdy liczony FLOP jest ukryty za kilkoma warstwami opóźnień spowodowanymi przez hiperwątkowate procesory, pamięci podręczne, wolną pamięć RAM, procesory wielościenne i automatyczną wektoryzację? Chodzi mi o to, że w granicach 5-10 nie można już przewidzieć czasu działania algorytmów bez pomiaru czasu. To było zupełnie inne w latach 50. i 60., kiedy ludzie zaczynali to liczenie FLOP.
Wolfgang Bangerth,

1

Tak, przestarzałe. Analiza algorytmiczna za pomocą klap lub dowolną inną metodą jest tylko tak użyteczna jak abstrakcyjny model maszyny, biorąc pod uwagę rozmiar problemu. Rzeczywista wydajność zależy zarówno od implementacji, jak i od sprzętu, a wraz z upływem czasu zmniejsza się możliwość zastosowania dowolnego modelu abstrakcyjnego w przypadku tego drugiego do rzeczywistości. Na przykład, w miarę jak równolegle wdrażasz złożony algorytm, taki jak dynamika molekularna, różne aspekty stają się ograniczeniem szybkości na innym sprzęcie, a analiza algorytmiczna nie ma nic wspólnego z obserwacjami. W pewnym sensie jedyną ważną rzeczą jest pomiar wydajności implementacji algorytmu (algorytmów) na danym typie sprzętu.

Czy takie abstrakcje są przydatne jako narzędzie do nauki? Tak, podobnie jak wiele modeli używanych do nauczania, są one użyteczne, o ile są umieszczone obok zrozumienia ograniczeń modelu. Klasyczna mechanika jest w porządku, o ile zdajesz sobie sprawę, że nie będzie działać na skalach o małej odległości lub dużej prędkości ...


-1

Nie odpowiadając na twoje pytanie, ale raczej dodając inną zmienną do rozważenia: należy wziąć pod uwagę cechy języka programowania. Na przykład Python sortużywa algorytmu Timsort , który został zaprojektowany (oprócz innych dobrych właściwości) w celu zminimalizowania liczby porównań, które mogą być potencjalnie wolne dla obiektów Python. Z drugiej strony, porównanie dwóch pływaków w C ++ płonie szybko, ale ich zamiana jest bardziej kosztowna, więc używają innych algorytmów.

Inne przykłady to dynamiczna alokacja pamięci (banalna na liście Pythona, szybka zarówno w środowisku wykonawczym, jak i programistycznym, po prostu .append()), w porównaniu z FORTRAN lub C, gdzie, chociaż jest to możliwe i szybsze, jeśli jest właściwie zaimplementowane, zajmuje znacznie więcej czasu i mózgu. Zobacz Python jest szybszy niż FORTRAN.


To prawda, ale, jak mówisz, nie odpowiada na pytanie. To na inny temat.
David Ketcheson

Cóż, w odpowiedniej analizie należy wziąć pod uwagę przy podejmowaniu decyzji, który algorytm zastosować.
Davidmh
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.