Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Kategoria: Kamery IP / Alarmy / Automatyka Bram
Montersi
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Obliczenia na float czy long ?

at91sam79 19 Mar 2017 22:11 1086 15
  • #1 19 Mar 2017 22:11
    at91sam79
    Poziom 9  

    Cześć,

    Zastanawiam się, czy w dzisiejszej dobie prędkości mikroprocesorów nadal warto wykonywać pewne obliczenia (np. trygonometrię czy obliczanie macierzy) konwertując liczby float na long (oczywiście mnożąc przez jakąś skalę np. 16bitów)???
    A co jeśli procesor ma wbudowany hardware'owy floating point? Cz wtedy warto przechodzi na liczby long?

    Kiedyś jak mikroprocesory były wolniejsze to jasne, było warto. A teraz?

    Zastanawiam się na tym ponieważ muszę zakodować pewien stary algorytm, który jest już zrobiony na longach. Algorytm jest dosyć skomplikowany i jak patrzę na te wszystkie skale (np. (138/ (21*128))/4098 a potem linijka niżej jeszcze jakaś operacja i >> 8 ) to zacząłem się zastanawiam. Skoro nie mam problemu z mocą obliczeniową to na liczbach zmiennoprzecinkowych kod byłby dużo czytelniejszy.

    Jak Wy podchodzicie do tego tematu?

    Pozdrawiam

  • #2 19 Mar 2017 22:29
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Jeśli mówimy o 32-bitowych układach, to ogólnie nie warto. Jak jest wspomaganie sprzętowe, to już w ogóle nie ma o czym mówić. Jedyny wyjątek może być wtedy, gdy mając algorytm na float, który jest już "matematycznie i algorytmicznie optymalny", układ się nie wyrabia (bo nie ma wspomagania sprzętowego) - wtedy można kombinować. Tyle że dopiero jak się nie wyrabia, a nie jak się komuś wydaje, że "raczej się nie wyrobi".

    Pewnie już kiedyś o tym tu pisałem, ale przypomnę. Jakiś czas temu robiłem algorytm na STM32F1, czyli układy 72MHz bez FPU. Algorytm był z góry na dół na float, trygonometria, macierze, równania kwadratowe itd. Algorytm ten odpowiadał za wyliczanie na żywo pozycji dwóch silników krokowych, tak aby przymocowane do nich lustro odbiło wiązkę światła w odpowiedni punkt docelowy - generalnie taka geometria w 3 wymiarach. Testy pokazały, że pełny obieg tego algorytmu zajmował max 35 tysięcy cykli (dla niektórych danych wejściowych spadało to do 18 tysięcy). Czy więc była potrzeba aby to optymalizować, gdy mogłem wyliczać 2000 pozycji na sekundę? BTW - w pierwszej wersji algorytm wywołałby z pewnością palpitację serca u niektórych zatwardziałych optymalizatorów, bo był w całości na double. Też się wyrabiało i działało niewiele wolniej (z tego co pamiętam, trochę mniej niż 2x wolniej).

    Inny przykład, też o nim pisałem. Sprzęt monitorujący, wszelkie obliczenia dla kilkudziesięciu "wielkości" (typu prąd, napięcie, moc, częstotliwość, temperatura, ...) robione na float. Układ to początkowo STM32F100, który ma max częstotliwość 24MHz. Całość na "ciężkim" RTOSie. Obliczenia 100x na sekundę. Całkowite obciążenie układu (zmierzone przez RTOSa) - ~15%, przy czym te wszystkie obliczenia to nie więcej niż 1/3 z tych 15%. Pewnie dałoby się to zoptymalizować i używać tylko zmiennych nie-float. Wtedy układ nudziłby się nie przez 85% czasu, tylko przez 88% czasu. Fascynujące <:

  • #3 19 Mar 2017 22:55
    Piotrus_999
    Poziom 39  

    Freddie Chopin napisał:
    Jak jest wspomaganie sprzętowe, to już w ogóle nie ma o czym mówić
    A są już w układach za 10zł, tak że pytanie o co walczyć?

  • #4 19 Mar 2017 23:03
    BlueDraco
    Specjalista - Mikrokontrolery

    Warto jeszcze uwzględnić problem precyzji - 32 bitowy int ma 32 bity, a 32-bitowy float - tylko 24; z kolei sprzętowe obliczenia na binary64 mają z popularnych mikroprocesorów na razie tylko nowsze wersje Cortex-M7.

    Jeśli mamy algorytm ze zmiennymi o dużej dynamice i jednostkę zmiennopozycyjną - to oczywiście warto użyć float. Jeśli nie mamy jednostki zmiennopozycyjnej, dynamika jest nieduża, zakresy wartości znane i wymagana precyzja powyżej 24 bitów - lepiej zrobić to w stałym przecinku, czyli w przeskalowanych intach. Skalowanie może być dowolne. Zwykle łatwiej zrobić skalowanie dziesiętne niż binarne, czyli przepisać wzór obliczeniowy dopisując w różnych miejscach mnożenia i dzielenia przez potęgi 10, tak, że by na końcu wynik się zgadzał.

  • #5 19 Mar 2017 23:12
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Wszystko fajnie z tym skalowaniem, pod warunkiem, że obliczenia ograniczają się do mnożenia, dzielenia, dodawania i odejmowania. Jak pojawiają się sinusy, pierwiastki, logarytmy itd, to już nie wiem czy komuś się będzie chciało pisać swoje własne funkcje lub szukać jakichś gotowców.

  • #6 19 Mar 2017 23:15
    Piotrus_999
    Poziom 39  

    BlueDraco napisał:
    Warto jeszcze uwzględnić problem precyzji
    W 99% problem jest wydumany, a dokładność wystarczająca aż nadto. Jak są jakieś problemy to wybranie sposobu zaokraglania załatwia kolejne .5%, a problemy pojawiają się dopiero przy jakiś tysiącach iteracji i kumulowaniu błędów - ale takie rzeczy to nieczęsty przypadek w uC.

    A tak przy okazji: kto miał jakiś prawdziwy problem z dokładnością wyliczeń na floatach w uC? (nie pytam o wydumane 4.999999 zamiast 5)

  • #7 19 Mar 2017 23:22
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Wbrew pozorom problem ten jest realny i bardzo skompilowany. Trafiłem na niego ostatnio kilkukrotnie, przy czym najwięcej problemów sprawiło mi "fused-multiply-add" i związane z nim cuda.

    http://stackoverflow.com/questions/42132260/g...used-multiply-add-floating-point-inaccuracies

    Dodatkowo trzeba było się zabezpieczać w kodzie liczącym wyniki równań kwadratowych, ponieważ zdarzało się, że braki precyzji powodowały wyliczenie ujemnej delty dla przypadków które powinny dawać wartość zero.

  • #8 19 Mar 2017 23:33
    BlueDraco
    Specjalista - Mikrokontrolery

    24-bitowa precyzja float, to niestety, Piotrusiu, bardzo realny problem. Weźmy np. typowy błąd początkujących - liczenie średniej z długiej sekwencji próbek. Sumujemy 100 milionów jedynek i wychodzi.... 16777216. ;)

  • #9 19 Mar 2017 23:49
    __Grzegorz__
    Poziom 27  

    Freddie Chopin napisał:

    Dodatkowo trzeba było się zabezpieczać w kodzie liczącym wyniki równań kwadratowych, ponieważ zdarzało się, że braki precyzji powodowały wyliczenie ujemnej delty dla przypadków które powinny dawać wartość zero.


    Czasem trzeba zastanowić się, czy nie trzeba zmienić podejścia do tematu.
    Zwykle zamiast liczyć "delty", lepiej użyć wzorów Viete'a.
    Mniej obliczeń, mniejsze błędy, niewrażliwość na niewspółmierne wartości współczynników (delta bliska 0, ale różna od 0)...

  • #10 19 Mar 2017 23:52
    Piotrus_999
    Poziom 39  

    BlueDraco napisał:
    Sumujemy 100 milionów jedynek i wychodzi.... 16777216


    Jeżeli obliczrenia robi się na "pałę", bez przemyślenia i zrozumienia jak działaja floaty, to Kolego @BlueDraco oczywiście tak. Mogę podać kolejne 100 innych przypadków durnoty obliczeniowej, a także jak kompilator teoretycznie dobrze napisane równanie optymalizuje do postaci niedokładnej. Idąc tym możemy uznać ze FPU są zbędne.

    Dodano po 1 [minuty]:

    __Grzegorz__ napisał:
    Czasem trzeba zastanowić się, czy nie trzeba zmienić podejścia do tematu.
    Wymaga to znajomości metod numerycznych itp. Wiedza obca 80% programistów nie piszących takich programów, i nie piszę o tym żeby wiedzę Kolegów zdyskredytować - sam mam bardzo szczątkowe wspomnienia i wiedzę, a podręcznik metod numerycznych na studiach powodował u mnie ataki śpiączki.

  • #11 20 Mar 2017 09:03
    Freddie Chopin
    Specjalista - Mikrokontrolery

    __Grzegorz__ napisał:
    Czasem trzeba zastanowić się, czy nie trzeba zmienić podejścia do tematu.
    Zwykle zamiast liczyć "delty", lepiej użyć wzorów Viete'a.
    Mniej obliczeń, mniejsze błędy, niewrażliwość na niewspółmierne wartości współczynników (delta bliska 0, ale różna od 0)...

    Matematykę miałem już dawno temu, jednak naprawdę nie widzę co te wzory mają tutaj ułatwić bez tworzenia jakichś zaawansowanych algorytmów "zgadujących". Standardowe podejście do rozwiązania takiego zagadnienia (czyli podstawienia) w efekcie daje... równanie kwadratowe. Próbowałem też coś znaleźć na necie i generalnie znalazłem wyprowadzenie standardowej formuły z deltą na podstawie wzoru Viete'a oraz opisy z faktoryzacją. Z tego co mi się kojarzy faktoryzacja jest jednym z najbardziej złożonych problemów numerycznych (nieprzypadkowo właśnie na niej opiera się znacząca większość algorytmów kryptograficznych), wiec naprawdę nie rozumiem jak użycie tych wzorów miałoby pomóc... Ale naprawdę chętnie się dowiem, więc byłbym zobowiązany za więcej info lub może jakiś link czy coś.

  • #12 20 Mar 2017 11:31
    at91sam79
    Poziom 9  

    Witam,

    Faktycznie nie napisałem o jakie mikrokontrolery chodzi.
    Będą to 32-bitowe ARMy.
    Jednak zastanawiam się nad uniwersalnością kodu pod kątem układów z FPU i bez.
    Chciałbym móc uruchamiać ten kod np. na AT91SAM7S256 który oczywiście nie ma FPU a jego prędkość to 48MHz.
    Ten sam algorytm chciałbym też uruchamiać na szybszym układzie AT91SAM9260, który pracuje na 100MHz ale też nie ma FPU.
    Czasem używam też ATSAMA5D36 z FPU, pracujący na 536MHz.

    Odnośnie precyzji, to w algorytmie o którym piszę jest ona dosyć ważna ponieważ jakieś 5% zmiennym posiada 31 bitową dokładność (i są zadeklarowane jako long long) - są to zmienne, których wartość zmienia się w pętli 100Hz o bardzo mały przyrost.
    Myślę że przechodząc na zapis zmiennoprzecinkowy te właśnie zmienne mogłyby być typu double.
    Pozostałe zmienne mają precyzję od 12 do 21 bitów (i są zadeklarowane jako long) więc spokojnie można je deklarować jako float.

    Jak rozumiem, przede wszystkim powinienem zastanowić się na tym czy mój uC wyrobi się dla kodu na floatach?

    Pozdrawiam

  • #13 20 Mar 2017 11:37
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Przepisz sobie algorytm z góry na dół używając typu double. Jeśli bedzie działać poprawnie, to sprawdź ile czasu się wykonuje. Jeśli się wyrabia z zapasem, to masz odpowiedź. Jeśli nie wyrabia się o niewielki procent (np. 5-20%), to pewnie zmiana niektórych obliczeń na float i inne optymalizacje pomogą. Jeśli nie wyrabia się o rząd wielkości (lub kilka), to wiadomo że nie ma sensu w to brnąć dalej, bo raczej cudów nie zdziałasz.

  • #14 20 Mar 2017 12:10
    trol.six
    Poziom 30  

    Freddie Chopin napisał:
    przy czym najwięcej problemów sprawiło mi "fused-multiply-add" i związane z nim cuda.

    Dokładność przy liczbach zmiennoprzecinkowych jest różna, zależy od rodzaju sprzętu oraz rodzaju instrukcji. Przeważnie mnożenie z dodawaniem może mieć większy błąd, niż wykonanie tych instrukcji z osobna.

    Dokładność też może być różna w zależności od rodzaju użytego kompilatora i sprzetu, jeśli korzystamy z programowego wsparcia.

    at91sam79 napisał:
    Zastanawiam się, czy w dzisiejszej dobie prędkości mikroprocesorów nadal warto wykonywać pewne obliczenia (np. trygonometrię czy obliczanie macierzy) konwertując liczby float na long (oczywiście mnożąc przez jakąś skalę np. 16bitów)???
    A co jeśli procesor ma wbudowany hardware'owy floating point? Cz wtedy warto przechodzi na liczby long?


    To czy jest sens korzystać zależy od potrzeb (typ algorytmu, dokładność itp) i widzimisie programisty. Jedynie z tego co sie orientuje, wraz ze złożonością obliczeń na liczbach zmiennoprzecinkowych rośnie błąd. Stąd w gałęziach nauki, liczy się często na liczbach 64-bit, bo w 32-bit błędy wychodzą dość szybko. Są tam jakieś sposoby liczenia i algorytmy, które dają te błędy mniejsze, ale przy bogactwie problemów matematycznych pewnie nie każdy ma czas na usprawnienia każdego.

  • #15 20 Mar 2017 18:32
    tzok
    Moderator Samochody

    Czasem też warto zadać sobie pytanie czy w ogóle opłaca się cokolwiek liczyć w uC. Kiedy jest jedna czy dwie zmienne, niewielki zakres zmienności, a obliczenia skomplikowane czasem warto je wyliczyć z góry z zadanym krokiem i umieścić w programie w formie tablicy, z ew. liniową aproksymacją wartości pośrednich. Takie podejście od lat jest stosowane np. w samochodowych sterownikach układów wtryskowo-zapłonowych (tzw. mapy).

 Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME