eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaProblem lekko OT, ale w WinAVR ;-)Re: Problem lekko OT, ale w WinAVR ;-)
  • 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.

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: