Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[wytwarzanie aplikacji] Określenie wymagań sprzętowych/systemowych aplikacji

Ostatnio zmodyfikowano 2013-09-19 20:13
Autor Wiadomość
pekfos
» 2013-09-19 14:43:58
Pierwszy lepszy profiler. Np gprof.
P-92320
DejaVu
» 2013-09-19 16:49:20
Możesz też w uproszczeniu liczyć liczbę linijek, np. masz 20 linijek kodu wewnątrz pętli to zakładasz, że 40 cykli Ci te linijki wciągną.
Równie dobrze mogą wciągnąć 80 cykli, albo 800. Nawet gdyby była mowa o asemblerze, to takie szacowanie jest bardzo optymistyczne. Poza tym, jak oszacować wywołanie?
Jesteś straszym pesymistą w kwestii szacowania złożoności kodu. 20, czy nawet 50 instrukcji nie wciągnie Ci 800 cyklów procesora. Szacowanie jest jak najbardziej poprawne, bo kod wynikowy kompilator i tak zoptymalizuje w stosunku do tego co programista napisał. Ty obecnie próbujesz udowodnić, że operacja dodawania może zabrać procesorowi 1 cykl jak i 50 cykli, co jest nieprawdą, bo operacja dodawania na liczbach całkowitych zawsze będzie miała nie więcej jak jeden cykl procesora, bo tak została ona zaprojektowana.

/edit:
Poza tym wszystko chodzi o oszacowanie złożoności kodu z grubsza, a nie o dokładne wyliczenia. Nie szacując niczego i pisząc algorytmy bez zastanowienia bardzo szybko wyczerpiesz zasoby w grach czasu rzeczywistego lub chociażby we wszelkiego rodzaju olimpiadach, gdzie chodzi właśnie o poprawę złożoności obliczeniowej algorytmów.
P-92321
akwes
» 2013-09-19 17:43:00
W procesorze, który projektowaliśmy na zajęciach na uczelni większość podstawowych operacji była wykonywana w jednym cyklu procesora. Mimo, że procesor był wolniutki (max 50Mhz) i z bardzo ograniczoną listą procesora to i tak bez problemu można było przeprowadzić odczyt z rejestrów, operacje w ALU czy FPU i zapis do rejestrów w jednym cyklu zegara (generalnie kilka mikrooperacji w jednym cyklu to normalność). Zdaje się, że ceną za taką wygodę była jedna dodatkowa magistrala. Kiedyś procesory nie potrafiły mnożyć (trzeba było wielokrotnie dodawać) dziś listy rozkazów są tak dopasowane i dobrze zaprojektowane, że pokrywają się poleceniami asma i tym co programista chce zrobić a procesory specjalistyczne potrafią mieć potężne kilkunasto-argumentowe rozkazy. Wpakowanie mnożarki do projektu to już nie problem. Wydaje mi się, że szacowanie w postaci "jedna instrukcja asma jako jeden cykl zegara" jest poprawne, dopóki poruszamy się w rejestrach procesora. No ale, że należy zawsze szacować pesymistyczne to liczenie x2 wydaje się gwarantować bezpieczeństwo pomyłki.

a skoro już szacujemy to może coś lekkiego o szacowaniu
http://en.wikipedia.org/wiki​/Back-of-the-envelope_calculation
http://www.cs.bell-labs.com/cm​/cs/pearls/bote.html
P-92322
pekfos
» 2013-09-19 17:57:47
Ty obecnie próbujesz udowodnić, że operacja dodawania może zabrać procesorowi 1 cykl jak i 50 cykli, co jest nieprawdą
Linijka kodu (C++) to nie zawsze jedna instrukcja. Instrukcja nie zawsze trwa jeden cykl procesora. 1, czy 2 cykle w takim szacowaniu robi sporą różnicę, a to zależy od procesora.
P-92323
DejaVu
» 2013-09-19 18:01:59
No ale w algorytmie do wykrywania kolizji, np. okrąg/okrąg masz co najwyżej 3 odejmowaia + 3 dodawania + 3 mnożenia + jedną instrukcję porównania, a to daje 9 operacji. Nawet jeżeli mechanizm wykrywania kolizji między dwoma obiektami będzie zrealizowany o metody wirtualne, to i tak nie wciągnie Ci wywołanie metody 41 cyklów, więc siłą rzeczy szacowanie jest poprawne. Poza tym jak już pisałem chodzi o szacowanie 'z grubsza', a nie o dokładne wyliczanie zapotrzebowania w MHz, bo do takich zabaw najlepiej robić już własne benchmarki i w zasadzie dopiero wtedy, gdy aplikacja będzie działała w odczuwalnym stopniu zbyt wolno.

Poza tym równie dobrze 3 linijki kodu kompilator może zwinąć w jedną instrukcję, bo linker będzie potrafił zoptymalizować istotnie jakiś fragment kodu. Generalnie rzecz biorąc nie ma co szukać dziury w całym, bo i tak cały czas poruszamy się w oszacowaniach kodu z 'grubsza', a nie o dokładnych szacowaniach, bo nie oglądamy wygenerowanego assemblerowego kodu i nie analizujemy cykli CPU pod kątem konkretnego procesora, lecz przypadek ogólny.
P-92324
Elaine
» 2013-09-19 19:59:55
Bądźmy szczerzy — czasy, kiedy dało się oszacować liczbę cykli potrzebną na wykonanie kodu skończyły się na przełomie lat osiemdziesiątych i dziewięćdziesiątych. Procesory przestały być taktowane tym samym zegarem, co pamięć, przestały również wykonywać jedną instrukcję w pełni i dopiero się zabierać za następną. Powstały i wciąż powstają też takie, które nie przejmują się kolejnością instrukcji i same sobie tą kolejność zmieniają w zależności od tego, jak im wygodnie i czy można to zrobić udając, że instrukcje jednak były wykonywane po kolei.

20, czy nawet 50 instrukcji nie wciągnie Ci 800 cyklów procesora
Ale jak najbardziej może, wystarczy kilka cache missów – czekanie na odczyt z albo zapis do pamięci to nawet kilkaset cykli! – a spudłować może praktycznie każda instrukcja odwołująca się do pamięci.

Innym dużym problemem są skoki. Bezpieczne są tylko bezwarunkowe skoki pod stały adres, ponieważ nie różnią się zbytnio od dodania stałej do rejestru, gdzie wartość stałej jest znana już po zdekodowaniu instrukcji. Jakiekolwiek skoki warunkowe (np. if i pętle) i pośrednie (np. switch, wskaźniki na funkcje i funkcje wirtualne) sprawiają już trudność, bo procesor albo nie wie, czy powinien skoczyć, albo nie wie, dokąd skoczyć. Procesory próbują zgadywać takie rzeczy. Jeśli im się uda, to super, skok jest darmowy lub prawie darmowy. Jeśli nie, trzeba opróżnić potoki i cofnąć procesor do stanu sprzed rozpoczęcia spekulacyjnego wykonania, na co potrzeba od kilkunastu do kilkudziesięciu cykli.

Kod jest liniowy i nie ma odwołań do pamięci? Oby nie było w nim dzielenia, bo dzielenie dwóch liczb całkowitych może bez problemu zająć 60 cykli, a w przypadku niektórych procesorów, jak intelowskie Atomy, znacznie więcej. Nie trzeba mieć doktoratu z matematyki, by policzyć, że 60∙20 to 1200, czyli liczba wyraźnie większa niż 800.

Ty obecnie próbujesz udowodnić, że operacja dodawania może zabrać procesorowi 1 cykl jak i 50 cykli, co jest nieprawdą
Mowa była o linijkach kodu, nie o dodawaniu, prawda?
Ale na x86 nawet dodawanie może tyle potrzebować, a nawet więcej – wszak istnieją instrukcje postaci add reg, mem i add mem, reg/imm, gdzie dostęp do pamięci jest, cóż, dostępem do pamięci.

No ale w algorytmie do wykrywania kolizji, np. okrąg/okrąg masz co najwyżej 3 odejmowaia + 3 dodawania + 3 mnożenia + jedną instrukcję porównania, a to daje 9 operacji. Nawet jeżeli mechanizm wykrywania kolizji między dwoma obiektami będzie zrealizowany o metody wirtualne, to i tak nie wciągnie Ci wywołanie metody 41 cyklów
Tu nawet nie potrzeba funkcji wirtualnych, by zgubić tyle cykli. Jeśli odejmowanie i dodawanie potrzebują jednego cyklu a mnożenie czterech, to biorąc pod uwagę fakt, że takie porównanie nie jest łatwe do przewidzenia przez procesor i jako takie często powoduje mispredykcje, wychodzi 3∙1 + 3∙1 + 3∙4 + 20, czyli 38.

To są rzeczy, których kompilator nie jest w stanie zoptymalizować. Masz w kodzie odwołanie do pamięci? Trzeba wygenerować odwołanie do pamięci. Masz warunek? Będzie skok warunkowy. Kompilator choćby chciał, to nie potrafi zagwarantować, że wykonanie kodu nie będzie musiało czekać na ściągnięcie danych z RAMu lub cofnięcie stanu CPU do tego sprzed mispredykcji.

tl;dr: procesory są zbyt skomplikowane, by dało się nawet z grubsza cokolwiek założyć.


linker będzie potrafił zoptymalizować istotnie jakiś fragment kodu
Kompilator. Dla linkera kod to tylko bajty, które w podany przez kompilator sposób musi zmienić, by się zgadzały adresy.
P-92329
akwes
» 2013-09-19 20:13:37

Procesory próbują zgadywać takie rzeczy.

Nie mogłem się powstrzymać przed dodaniem ciekawego tematu o tym na stackoverflow.

P-92330
1 2 « 3 »
Poprzednia strona Strona 3 z 3