Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C][Atmega16] - Fixed point z GCC używając Atmel studio 7

revcorey 12 Lut 2016 23:49 780 8
  • #1 12 Lut 2016 23:49
    revcorey
    Poziom 11  

    Panowie postanowiłem wykonać test wbudowanych w atmel studio typów fixed point vs float. Na razie tylko samych _Accum z saturacją ale to co zobaczyłem nie napawa optymizmem gdzie jest błąd?Dodam że
    -atmel studio 7,
    -wewnętrzny zegar 8MHz
    -Atmega16.
    -Do pomiaru czasu używam timer 1.
    Najpierw kod, testujemy 4 działania +,-,*,/ dla typu _Accum i float. Do odmierzania czasu używam timera 1, z preskalerem równym 1. Przed działaniem zeruje TCNT1 po działaniu zapisuję do zmiennej tymczasowej wartość rejestru TCNT1, wyświetlam i znowu zaczynam kolejne obliczenia.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czas na wyniki(wartość TCNT1):
    Dodawanie:
    Accum float
    32 123
    dla dodawanie jeszcze przeliczę na mikro sekundy to będzie 256 mikrosekund dla Accum, dla float 984 mikrosekundy.
    odejmowanie:
    30 132

    Mnożenie
    245 160
    Dzielnie:
    1164 499

    Teraz zbadałem jeszcze pamięć tzn. w programie od komentowany był tylko _Accum lub float i w pętli jedno działanie + lub - lub * lub /, czyli np.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Rekompilacja, sprawdzenie ile zajmuje, zmiana typu działania rekompilacja i tak dla każdego działania i typu.
    wyniki:
    dodawanie/odejmowanie:
    708 bytes 4,3% accum
    1070 bytes 6,5% float
    mnożenie:
    918 bytes 5,6% accum
    1070 bytes 6,5% float
    dzielnie:
    1524 bytes 9,3% accum
    1080 bytes 6,6% float

    Aż chce się rzec wtf?!używanie typów fixed point z gcc kontra float jest wydajniejsze tak naprawdę tylko przy dodawaniu i odejmowaniu? Czy to wina kompilatora wbudowanego w AS7? Czy mam jakiś błąd w kodzie którego nie widzę?

    0 8
  • #2 13 Lut 2016 15:51
    tmf
    Moderator Mikrokontrolery Projektowanie

    Odpal te przykłady w symulatorze i zobacz ile ich wykonanie zajmuje cykli. Taki pomiar jest prostszy i dokładniejszy i timer zastosowany tak jak to pokazałeś.
    Implementacja typów stałopozycyjnych jest zewnętrzna w stosunku do gcc i zapewne nie jest superoptymalna. Nie porównywałem tego, więc się nie wypowiem na ile wiarygodne są twoje wyniki. Weź też pod uwagę, że trywialność zastosowanych porównań może powodować nieprzewidziane wyniki. Np. dłgość kodu - nie spodziewałbym się wykazania dużych różnic na przykłądzie kodu w którym masz tylko kilka obliczeń i maszę kodu niezwiązanego z arytmetyką.

    0
  • #3 13 Lut 2016 16:20
    revcorey
    Poziom 11  

    Sprawdzałem w necie. Gość kiedyś sprawdzał coś podobnego na symulatorze wyszło mu że dodawanie/odejmowanie jest dużo szybsze(mniej więcej się zgadza), mnożenie niewiele a dzielenie wolniejsze.
    Link
    Fakt faktem przykład jest prosty, myślę że w najbliższym czasie pokuszę się o implementację jakiegoś bardziej zawiłego algorytmu, i dam znać jak poszło.

    Ale zastanawia mnie jedna rzecz. Rozmiar, abstrahując od szybkości obliczeń, prosty przykład zmienne z atrybutem volatile i te proste operacje a tak duże zmiany rozmiaru? i to wręcz na niekorzyść fixed-point. Cóż postaram się dociec w najbliższym czasie o co tu chodzi.

    0
  • #4 17 Lut 2016 18:31
    revcorey
    Poziom 11  

    Ok,
    Zrobiłem dodatkowy test, mamy dwie funkcję:
    - jedna to prosty filtr(Link)
    -Obliczanie pierwiastka kwadratowego zgodnie z algorytmem(trochę dzielenia, trochę mnożenia i dodawania/odejmowania). Link
    Robię nadal na żywca nie na symulatorze, chodzi mi bardziej o to które rozwiązanie jest lepsze, a dokładność ma drugorzędne znaczenie.
    Ustawienia:
    -Wewnętrzne 8 mhz,
    -Preskaler dla timera1 64.
    Kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Wyniki z kompilatora dla float:
    Program Memory Usage : 2160 bytes 13,2 % Full
    Data Memory Usage : 40 bytes 3,9 % Full
    Wartość timera1:5209

    Wyniki dla kompilatora z accum:
    Program Memory Usage : 1648 bytes 10,1 % Full
    Data Memory Usage : 40 bytes 3,9 % Full
    Wartośc timera1:3995

    Jak widać operację na fixed point z gcc są jednak szybsze niż na float i zajmują mniej miejsca(patrz uwaga poniżej).

    edit:
    Zrobiłem jeszcze jeden test tzn. tak samo jak w poście nr. 1 wprowadziłem saturację:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Wyniki:
    Program Memory Usage : 2462 bytes 15,0 % Full
    Data Memory Usage : 40 bytes 3,9 % Full
    wartość timera1:5713

    Wprowadzenie saturacji niestety powoduje wolniejsze niż float obliczenia + większy rozmiar.

    0
  • #5 17 Lut 2016 18:44
    grko
    Poziom 33  

    Troche te testy nie są miarodajne. Brakuje np prostego testu mnożenia z akumulacją co jest absolutną podstawą w DSP. Prosta implementacja filtru FIR oraz IIR dałaby wiecej informacji co jest lepsze w praktyce. Wydaje mi się, że niepotrzebnie stosujesz volatile co może dać gorszy rezultat testu.

    0
  • #6 17 Lut 2016 18:48
    revcorey
    Poziom 11  

    Zastanawiałem się nad filtrem IIR/FIR, może się jeszcze za to wzmę aczkolwiek widziałem ich implementację częściowo robioną w asm. Wiesz też dobre pytanie na ile używać atmegi do DSP :) Po prawdzie widziałem estymator momentu elektromagnetycznego na 8051 ale dziś? Ale może spróbuję.
    co do volatile użyłem z premedytacją, zobaczę sobie jeszcze później jak to tam działa bez.
    Ale myślę że jedna trend widać.

    0
  • #8 17 Lut 2016 19:02
    revcorey
    Poziom 11  

    Ja? Osobiście z ciekawości. Być może informacja o tym jak to wydajnościowo mniej więcej wygląda kiedyś się komuś przyda.

    0
  • #9 17 Lut 2016 20:45
    tmf
    Moderator Mikrokontrolery Projektowanie

    revcorey napisał:


    Wprowadzenie saturacji niestety powoduje wolniejsze niż float obliczenia + większy rozmiar.


    Zauważ, że saturacja dla fixed point to nie to samo co dla float. W przypadku saturacji masz +/- max, a dla float masz +/-INF, czyli zupełnie coś innego. Wykrycie INF dla float jest o wiele prostsze i mniej czasochłonne. Z drugiej strony fixed point math to ciągle swego rodzaju nowość i implementacja tego, szczególnie dla frontendu avr w gcc nie jest perfekcyjna. Jeśli zależy ci na jakiś konkretnych operacjach to warto sprawdzić ich implementację w avr-gcc i ew. dodać własną implementację. W necie są dostępne szablony (wymagane INSNS) dla gcc, więc tu hackowanie kompilatora nie wymaga jakiejś kosmicznej wiedzy.
    Weź też pod uwagę, że fixed point i float to nie są typy do zamiennego stosowania - dla fixed point poza (zazwyczaj) szybszymi obliczeniami i (zazwyczaj) krótszym kodem masz ściśle zdefiniowane granularity, czego nie ma dla float.

    0