eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaProblem lekko OT, ale w WinAVR ;-) › Re: Problem lekko OT, ale w WinAVR ;-)
  • Path: news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!new
    sfeed.neostrada.pl!atlantis.news.neostrada.pl!news.neostrada.pl!not-for-mail
    From: "T.M.F." <t...@n...mp.pl>
    Newsgroups: pl.misc.elektronika
    Subject: Re: Problem lekko OT, ale w WinAVR ;-)
    Date: Fri, 12 Jun 2009 11:42:26 -0400
    Organization: TP - http://www.tp.pl/
    Lines: 150
    Message-ID: <h0t8g2$62t$1@nemesis.news.neostrada.pl>
    References: <h0qku7$a6o$1@atlantis.news.neostrada.pl>
    <h0r3ok$c87$1@atlantis.news.neostrada.pl>
    <5...@4...com>
    <h0r8h1$fpo$1@nemesis.news.neostrada.pl> <h0rfu4$r83$1@news.mm.pl>
    <h0rjnq$etf$2@news.wp.pl> <h0rkmu$1ol$2@nemesis.news.neostrada.pl>
    <h0rkdf$4nb$2@news.mm.pl> <h0rti7$969$2@atlantis.news.neostrada.pl>
    <h0t1ob$o5f$1@atlantis.news.neostrada.pl>
    NNTP-Posting-Host: dvi241.neoplus.adsl.tpnet.pl
    Mime-Version: 1.0
    Content-Type: text/plain; charset=UTF-8; format=flowed
    Content-Transfer-Encoding: 8bit
    X-Trace: nemesis.news.neostrada.pl 1244800322 6237 83.22.42.241 (12 Jun 2009 09:52:02
    GMT)
    X-Complaints-To: u...@n...neostrada.pl
    NNTP-Posting-Date: Fri, 12 Jun 2009 09:52:02 +0000 (UTC)
    User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1b3pre) Gecko/20090513
    Fedora/3.0-2.3.beta2.fc11 Thunderbird/3.0b2
    In-Reply-To: <h0t1ob$o5f$1@atlantis.news.neostrada.pl>
    Xref: news-archive.icm.edu.pl pl.misc.elektronika:565237
    [ ukryj 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: