-
Data: 2009-06-12 15:42:26
Temat: Re: Problem lekko OT, ale w WinAVR ;-)
Od: "T.M.F." <t...@n...mp.pl> szukaj wiadomości tego autora
[ pokaż wszystkie nagłówki ]W dniu 12.06.2009 03:54, Zbych pisze:
> T.M.F. pisze:
>
>> No zagladam dosyc czesto przy okazji debuggowania tego co napisalem.
>> Jakis koszmarnych brakow optymalizacji nie zauwazylem. Mozesz podac
>> konkretny przyklad w C, ktory jest zle optymalizowany? To zawsze mozna
>> zglosic jako bug.
>
> To zależy co kto uważa za koszmarne. Poniżej parę przykładów, ale
> wątpię, żeby komuś chciało się to czytać.
>
> Wszystkie przykłady były optymalizowane na rozmiar.
>
>
> ----------------------------------------------------
-----
> Testowanie warunków logicznych:
>
> #define PIN1_IS_LOW (!(PINB & (1<<PINB7)))
> #define PIN2_IS_LOW (!(PINB & (1<<PINB6)))
>
> volatile uint8_t a;
> asm volatile(";start");
> a = (PIN1_IS_LOW || PIN2_IS_LOW);
> asm volatile(";stop");
>
> Pomijając już tą nieszczęsną promocję do inta, to najbardziej w tym
> kodzie rozwaliło mnie wyłuskiwanie 6 bitu.
Promocja do int wynika ze standardu C wiec trudno tu robić zarzut
kompilatorowi. Żeby to ominąć wystarczy explicite typecastowac.
> Delikatna modyfikacja kodu:
>
> if (PIN1_IS_LOW || PIN2_IS_LOW) a = true;
> else a = false;
Tu faktycznie jest jakiś problem z optymalizacja. Warto to zgłosić jako Bug.
> ----------------------------------------------------
------
> Przygotowanie ramki na stosie dla 5 parametrów 16-bitowych:
>
> 1637 0068 ADB7 in r26,__SP_L__
> 1638 006a BEB7 in r27,__SP_H__
> 1639 006c 1A97 sbiw r26,10
> 1640 006e 0FB6 in __tmp_reg__,__SREG__
> 1641 0070 F894 cli
> 1642 0072 BEBF out __SP_H__,r27
> 1643 0074 0FBE out __SREG__,__tmp_reg__
> 1644 0076 ADBF out __SP_L__,r26
>
> Przy dwóch parametrach:
>
> 1751 010e 00D0 rcall .
> 1752 0110 00D0 rcall .
>
> Łatwo policzyć, że poniżej 8 parametrów bardziej opłaca się wersja z
> rcall (program optymalizowany na rozmiar).
Tu sprawa nie jest tak oczywista. Co prawda rcall są krótsze w sensie
długości kodu, ale zajmuja 3 takty zegara. To co generuje gcc zajmuje
niezależnie od długości ramki 9 taktow, czyli 3 rcall. Sytuacja wyglada
jeszcze gorzej kiedy PC jest 22 bitowy - wtedy 4 takty. Wiec jak sadze
wybrano pewien kompromis pomiedzy długością kodu a czasem egzekucji.
>
>
>
> ----------------------------------------------------
-------
> Adresowanie struktur i pobieranie adresów z flasha:
>
> typedef struct{
> const prog_char * a;
> const prog_char * b;
> const prog_char * c;
> const prog_char * d;
> }Aqq;
>
> prog_char s[] = "Aqq";
>
> Aqq PROGMEM tab[]={
> {s,s,s,s},
> {s,s,s,s},
> {s,s,s,s},
> {s,s,s,s},
> };
>
> asm volatile (";start");
> for (uint8_t i = 0; i < tab_size(tab); i++){
> blabla( pgm_read_word( &tab[i].a ), pgm_read_word( &tab[i].b ),
> pgm_read_word( &tab[i].c ), pgm_read_word( &tab[i].d ) );
> }
> asm volatile (";stop");
>
>
> Pierwszy problem to wyliczanie adresu w flashu:
To zalezy zapewne od zdefiniowanej przez ciebie funkcji tab_size(tab).
Kompilator za każdym obiegiem petli musi ja wywołać, żeby wilczyć wynik
dla danego argumentu - dlaczego? Bo ja źle zdefiniowałeś.
> Pomimo, że jest (czy raczej mogłoby być) użyte adresowanie z
> postinkrementacją, to adresy kolejnych elementów są i tak przed każdym
> pobraniem na nowo wyliczane. W przykładzie, który podałem daje to 12
> niepotrzebnych instrukcji w każdym obiegu tej krótkiej pętli i dodatkowo
> zajętą parę rejestrów R19:R18.
>
> Drugi problem, to wyliczanie od początku adresu komórki w tablicy przy
> każdym obiegu pętli:
>
Sprawdziłem to u siebie i nic takiego się nie dzieje. Musiałem
zdefiniować dodatkowo dziwna funkcje Babla bo mi kompilator to
optymalizował i ją wywalał.
> Wystarczy prosty myk ze wskaźnikiem i pętla się skraca:
>
> asm volatile (";start");
> for (uint8_t i = 0; i < tab_size(tab); i++){
> const Aqq * p = &tab[i];
> blabla( pgm_read_word( &p->a ), pgm_read_word( &p->b ), pgm_read_word(
> &p->c ), pgm_read_word( &p->d ) );
> }
Tu problem jest bardziej dyskretny. C przy adresowaniu elementów
struktury używa adresowania z przemieszczeniem. W pierwszym przykładzie
pobierasz adresy konkretnego elementu, stad za każdym razem są pobierane
pełne adresy. Za drugim razem używasz adresu struktury i offsetów do jej
elementów (operator -> generuje offsety). Zauważ, że gdyby pola tej
struktury były duże - powyżej 127 bajtów, to i tak zaszłaby konieczność
pobrania pełnego adresu, bo offset byłby większy niż maksymalne
przemieszczenie. Oczywiście kompilator może sobie z tym poradzić,
niestety tu wychodzi jedna z wad gcc - jest to kompilator pod duże
procki, a AVR jest tylko specyficzną wspieraną platformą. Żeby ta
optymalizacja dobrze zadziałała trzebaby nieźle zamieszać w kodzie gcc.
A w sumie jeśli często się ogląda sesje typu połączony C+assembler to
człowiek szybko się uczy jaka składnia języka jest optymalna. Akurat
przy pętlach ze względu na specyfikę listy rozkazów AVR można się nieźle
wykazać.
> A podobno gcc ma super optymalizator do pętli (widocznie moja wersja
> gdzieś go zgubiła).
Jak ci nie pasuje gcc to zaproponuj cos lepszego... nie mowiac juz o
tym, ze masz kod źródłowy wiec możesz się wykazać dla potomności :)
--
Inteligentny dom - http://idom.wizzard.one.pl
http://idom.sourceforge.net/
Teraz takze forum dyskusyjne
Zobacz, wyslij uwagi, dolacz do projektu.
Następne wpisy z tego wątku
- 12.06.09 15:47 T.M.F.
- 12.06.09 10:29 Zbych
- 12.06.09 17:14 T.M.F.
- 12.06.09 11:27 Zbych
- 12.06.09 16:46 J.F.
- 12.06.09 20:15 Grzegorz Kurczyk
- 12.06.09 20:30 J.F.
- 12.06.09 20:30 Zbych
- 13.06.09 01:35 Grzegorz Kurczyk
- 13.06.09 06:43 Grzegorz Kurczyk
- 13.06.09 07:28 Zbych
- 13.06.09 07:44 J.F.
- 13.06.09 14:35 T.M.F.
- 13.06.09 14:36 T.M.F.
- 13.06.09 14:37 T.M.F.
Najnowsze wątki z tej grupy
- DS1813-10 się psuje
- Taki tam szkolny problem...
- LIR2032 a ML2032
- SmartWatch Multimetr bezprzewodowy
- olej psuje?
- Internet w lesie - Starlink
- Opis produktu z Aliexpress
- No proszę, a śmialiście się z hindusów.
- Zewnętrzne napięcie referencyjne LM385 1,2V -> 100mV dla ICL7106, Metex M-3800
- karta parkingowa
- Wl/Wyl (On/Off) bialy/niebieski
- I3C
- Pytanie o transformator do dzwonka
- międzymordzie USB 3.2 jako 2.0
- elektronicy powinni pomysleć o karierze elektryka
Najnowsze wątki
- 2024-11-25 Karty przedpłacone (podarunkowe) Google Play - pytanie do korzystających
- 2024-11-26 wina Tóska
- 2024-11-26 Rewolucja/Rewelacja!
- 2024-11-25 grupa ożyła ;)
- 2024-11-24 Być jak Clint
- 2024-11-24 Rura kanalizacja konceptu Franke = problem
- 2024-11-25 Wrocław => Lead Java EE Developer <=
- 2024-11-25 Warszawa => Business Development Manager - Network and Network Securit
- 2024-11-25 Kraków => Programista Full Stack (.Net Core) <=
- 2024-11-25 Lublin => Senior PHP Developer <=
- 2024-11-25 Karlino => Konsultant wewnętrzny SAP (FI/CO) <=
- 2024-11-25 Warszawa => ECM Specialist / Consultant <=
- 2024-11-25 Katowice => Regionalny Kierownik Sprzedaży (OZE) <=
- 2024-11-25 Warszawa => Senior Frontend Developer (React + React Native) <=
- 2024-11-25 Lublin => Inżynier Serwisu Sprzętu Medycznego <=