logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C]Zmienna lokalna vs globalna, a szybkość wykonywania programu przerwania

kamil94goldman 08 Lis 2017 00:11 2520 14
  • #1 16808592
    kamil94goldman
    Poziom 3  
    Witam,

    Mam takie pytanie:

    Załóżmy, że w programie obsługi przerwania potrzebuje zmienną, która nie będzie wykorzystywana poza obsługą tego przerwania(czyli można zadeklarować zmienną lokalną w przerwaniu). Lecz zastanawia mnie, jaka jest różnica pod względem szybkości wykonywania programu, gdyby zamiast zmiennej lokalnej, zadeklarować na początku programu głównego, zmienną globalną z specyfikatorem volatile, zamiast tamtej zmiennej lokalnej.

    Zmienna globalna będzie deklarowana na początku programu, przez co, cały czas będzie zajmowała miejsce w pamięci RAM, a zmienna lokalna będzie deklarowana w momencie wykonywania przerwania i kasowana po wyjściu z niego. Więc w jakim przypadku, procedura obsługi przerwania, wykona się szybciej?
  • Pomocny post
    #2 16808610
    WX3V
    Poziom 18  
    Zadałeś pytanie: Jak działa mój kompilator C ?
    Zatem jeśli zmienna lokalna (ulotna) jest pamiętana w rejestrze procesora, po odłożeniu na Stos jej początkowej wartości, to będzie ona dostępna szybciej niż zmienna globalna. Natomiast jeśli jest pamiętana w SRAMie to czas dostępu do niej nie powinien różnić się od czasu dostępu do zmiennej globalnej.
    Chcąc nie chcąc musisz zajrzeć do opisu działania kompilatora lub wykonać eksperyment stosując symulator lub emulator procka. Innych wyjść nie widzę.
    Pozdrawiam.
  • Pomocny post
    #3 16808743
    Tomq
    Poziom 38  
    Dla pewności można określić typ jako "uint_fast8_t" z "stdint.h". Nie zawsze będzie to szybsze niż zwykły uin8_t, ale na pewno nie wolniejsze.
    Co do polityki cenowej Atmela i ST, to różnica w cenie w przypadku debugowania jest kolosalna.
  • #4 16808788
    JacekCz
    Poziom 42  
    kamil94goldman napisał:
    ... , gdyby zamiast zmiennej lokalnej, zadeklarować na początku programu głównego, zmienną globalną z specyfikatorem volatile, zamiast tamtej zmiennej lokalnej.


    Kolejne przesądy volatile? Musisz jeszcze splunąć 3x przez lewe ramię przy pełni księżyca.

    volatile, w sensie o który pytasz, ma odwrotny sens "proszę cię kompilatorze, NIE TRZYMAJ wartości zmiennej w rejestrze i ODKŁADAJ ją do RAM-u".
    Zmienna ma oddawać sens programu. Przy okazji, statystycznie najczęściej to, co jest w dobrym stylu, jest szybsze (albo nie jest wolniejsze).

    Jak masz problem z dwoma taktami CPU, tzn masz grubszy problem. Zgaduję: marnujesz wiele, wiele taktów na co innego.


    EDIT: w darmowych narzędziach da się skompilować C do listingu kodu maszynowego AVR, i są dostępne tabele ile rozkazy trwają. To jest chyba ostatnia linia procesorów (nie posiadająca cache itd), że taka kalkulacja jeszcze ma jakiś sens.


    Dodano po 2 [minuty]:
    kamil94goldman napisał:

    Zmienna globalna będzie deklarowana na początku programu, przez co, cały czas będzie zajmowała miejsce w pamięci RAM, a zmienna lokalna będzie deklarowana w momencie wykonywania przerwania i kasowana po wyjściu z niego. Więc w jakim przypadku, procedura obsługi przerwania, wykona się szybciej?


    A to źródło, które sugeruje volatile, nie objaśnia ile kosztuje 'zadeklarowanie' i 'skasowanie' zmiennej lokalnej?
  • #5 16809164
    kamil94goldman
    Poziom 3  
    WX3V napisał:
    Zatem jeśli zmienna lokalna (ulotna) jest pamiętana w rejestrze procesora, po odłożeniu na Stos jej początkowej wartości, to będzie ona dostępna szybciej niż zmienna globalna.

    Czyli, generalnie zmienna lokalna zadeklarowana w przerwaniu, też będzie odłożona przez kompilator do rejestru i potem wszystkie operacje będą wykonywane na tym rejestrze?

    A jak wygląda sprawa z zmienną lokalną z specyfikatorem "static" ? Taka zmienna, jest niby tworzona w pamięci RAM, tam gdzie zmienne globalne, ale jej dostęp jest możliwy tylko dla funkcji/przerwania w którym została zadeklarowana. Czy taka zmienna też zostanie "przeniesiona" do rejestru i na tym rejestrze będą wykonywane działania?

    Korzystam z atmel studio
  • Pomocny post
    #6 16809248
    JacekCz
    Poziom 42  
    kamil94goldman napisał:
    WX3V napisał:
    Zatem jeśli zmienna lokalna (ulotna) jest pamiętana w rejestrze procesora, po odłożeniu na Stos jej początkowej wartości, to będzie ona dostępna szybciej niż zmienna globalna.

    Czyli, generalnie zmienna lokalna zadeklarowana w przerwaniu, też będzie odłożona przez kompilator do rejestru i potem wszystkie operacje będą wykonywane na tym rejestrze?

    A jak wygląda sprawa z zmienną lokalną z specyfikatorem "static" ? Taka zmienna, jest niby tworzona w pamięci RAM, tam gdzie zmienne globalne, ale jej dostęp jest możliwy tylko dla funkcji/przerwania w którym została zadeklarowana. Czy taka zmienna też zostanie "przeniesiona" do rejestru i na tym rejestrze będą wykonywane działania?

    Korzystam z atmel studio


    Na AVR każde działanie jest ostatecznie wykonane na rejestrach. Pytanie jest jak długo w tych rejestrach przebywa, zmienna 'auto' (tak się mówi - nie ma na to słowa kluczowego, "prawdziwa" niestatyczna zmienna lokalna) może nigdy nie mieć obrazu w pamięci, lub być tam obecna. Zależy od optymalizatora.

    Mam wrażenie, ze kombinujesz. SENS, naukowo mówiąc semantyka zmiennej 'static' jest zupełnie inny niż 'auto' (w przerwaniach nawet BARDZO). Nie ma sensu dla pozornych zysków (jednego bajta/pojedynczych taktów) zmieniać istoty algorytmu, wcześniej czy później się zemści. Pokaż proponowany kod.
  • Pomocny post
    #7 16809291
    WX3V
    Poziom 18  
    kamil94goldman napisał:
    Czyli, generalnie zmienna lokalna zadeklarowana w przerwaniu, też będzie odłożona przez kompilator do rejestru i potem wszystkie operacje będą wykonywane na tym rejestrze?

    Dokładnie tak będzie.

    kamil94goldman napisał:
    A jak wygląda sprawa z zmienną lokalną z specyfikatorem "static" ? Taka zmienna, jest niby tworzona w pamięci RAM, tam gdzie zmienne globalne, ale jej dostęp jest możliwy tylko dla funkcji/przerwania w którym została zadeklarowana. Czy taka zmienna też zostanie "przeniesiona" do rejestru i na tym rejestrze będą wykonywane działania?

    Dla większości przypadków operacje asemblerowe są wykonywane przy użyciu rejestrów. Zatem i zmienna static będzie musiała być przeniesiona do któregoś z nich. Aczkolwiek zawartość tego rejestru nie będzie chroniona czyli rejestr będzie mógł być nadpisany w następnych instrukcjach. Natomiast kolejne odwołanie (w tej samej procedurze) do takiej zmiennej będzie powodowało ponowne jej ściągnięcie z przestrzeni SRAM lub Flash i wpisanie do któregoś z rejestrów - niekoniecznie tego samego co poprzednio.
    Cóż, zwykle kilka kolejnych "przebiegów kompilacji" służy minimalizacji długości kodu wynikowego, a nie minimalizacji czasu jego wykonania. Zresztą taka funkcja celu jest zdecydowanie trudniejsza do praktycznego wykonania.
    W przypadku konieczności minimalizacji czasu obsługi przerwania najczęściej pisze się procedurę obsługi w asm'ie wpisując wyniki w miejsca zmiennych z C usytuowanych w SRAMie. Niestety wymaga to "podglądania" pracy kompilatora C, a dokładniej tego jak organizuje on zmienne w SRAMie. Jest z tym nieco "zachodu".

    kamil94goldman napisał:
    Korzystam z atmel studio

    Też korzystam z tego pakietu. Aczkolwiek mam świadomość, że niektóre z komercyjnych pakietów są znacznie lepiej dopracowane i mają znacznie lepsze możliwości.
    Pozdrawiam.
  • #8 16809403
    kamil94goldman
    Poziom 3  
    JacekCz napisał:
    Pokaż proponowany kod.


    Chodzi mi o moją funkcję regulacji, regulatora PI, w przetwornicy impulsowej. Czy można tutaj może coś lepiej zrobić? (mikrokontroler XMEGA)

    Kod: C#
    Zaloguj się, aby zobaczyć kod
  • #9 16809475
    BlueDraco
    Specjalista - Mikrokontrolery
    To, co kompilator zrobi ze zmienną, zależy od fantazji jego autora, wybranego stopnia optymalizacji, liczby zmiennych zadeklarowanych w procedurze i 10 innych czynników. Nie należy polegać na tym, że w jakiejś sytuacji kompilator potraktował daną zmienną w określony sposób (np. umieścił w rejestrze). Teoretycznie np. zmienna volatile może też być w rejestrze.
  • #10 16809580
    WX3V
    Poziom 18  
    BlueDraco napisał:
    To, co kompilator zrobi ze zmienną, zależy od fantazji jego autora...

    Z "bólem serca" przyznam, że masz rację. Dlatego pisałem tylko o zasadach (pobożnych życzeniach), według których należy pisać kompilatory. Myślę jednak, że zasada związana z alokacją zmiennych w pamięci SRAM (zgodnie z ich typem i/lub kolejnością w deklaracjach) jest przestrzegana. Gdyby tak nie było to bardzo utrudnionym byłoby pisanie "wstawek" asemblerowych, a to deprecjonowałoby wartość kompilatora w oczach użytkowników - głównie tych nieco bardziej zaawansownych. Zatem napisanie programu w C z obsługą przerwań w asm'ie powinno być realnym rozwiązaniem. Jego jedyną trudnością jest zdekodowanie lub przeczytanie informacji związanej z układaniem zmiennych w SRAM stosowanym przez używany kompilator.
    Natomiast sporą niedogodnością może być to, że ten sam kod źródłowy skompilowany innym kompilatorem może nie działać poprawnie. Nie widzę też szans na stworzenie jakiegoś standardu w tej kwestii.
    Pozdrawiam.
  • #11 16809625
    Sareph
    Poziom 24  
    WX3V napisał:
    Myślę jednak, że zasada związana z alokacją zmiennych w pamięci SRAM (zgodnie z ich typem i/lub kolejnością w deklaracjach) jest przestrzegana.
    Żebyś się nie zdziwił. W końcu GCC z jakiegoś powodu ma parametr "-fno-toplevel-reorder".
  • Pomocny post
    #12 16809627
    Konto nie istnieje
    Poziom 1  
  • #13 16809856
    JacekCz
    Poziom 42  
    1. Podrzucę Ci pomysł, pomocny lub nie.
    Zrobiłem PWN Atmega8 (czyli straszny dziad) generator miłego dla ucha sinusoidalnego dźwięku (w oparciu o przerwanie timera). Czystość uzyskałem, gdy na samym początku przerwania ustawiałem wartość ze zmiennej do PWM, a potem mogłem ją sobie opracowywać "na nastepny raz" do woli, nieczuły że obliczenia (mnożenia, if'y) trwają za każdym razem nieco inaczej. Inaczej dzwięk charczał.

    2. Z jaką częstotliwością będzie to przerwanie?
    Albo nie mamy problemu wcale, i cała dyskusja o pojedynczych taktach nie ma sensu - albo mamy problem i np głupie dzielenie zjada więcej taktów niż reszta kodu (może koledzy sprostują, jak się dzieli w XMega?)

    3. Zgadzam się z @Marek_Skalski , szczegółowe rady 1 i 2 nie oznaczają, że sama idea algorytmu przetwornicy mnie przekonuje.

    4. dzięki, że zauważasz odmienny sens 'static'. To jest decyzja na poziomie projektowania algorytmu, uzyskanie konkretnego efektu, a nie pojedynczych taktów.

    5. aha, jeszcze jedno, rozwiązanie zagadki :) powołanie zmiennej lokalnej C jest w zasadzie za darmo, zależy jak to oceniamy, a kasowanie zupełnie za darmo (to nie jest alokowanie na heap'ie)

    Dodano po 41 [sekundy]:
    WX3V napisał:

    Dla większości przypadków operacje asemblerowe są wykonywane przy użyciu rejestrów.

    Na niektórych architekturach oblicza się TYLKO w oparciu o rejestr, AVR do nich nalezy (są takie, które zrobią proste obliczenia w oparciu o zmienną RAM). Ale za to rejestrów jest więcej, i są niemal równoważne, znakomicie zwiększa to szanse optymalizatora (w odróżnieniu od Intela 8086, gdzie każdy z niewielu rejestrów jest nieco inny) . Czasy genialnych programistów asemblerowych również z tych powodów odchodzą w przeszłość, jest zupełnie odwrotnie niż 30 lat temu, od wielu generacji cała architektura CPU jest pod wydajną automatyczną kompilację (a nie programista dziubie z niuansami procesora - z kolei jest trudność intelektualnego ogarnięcia przez człowieka kilkunastu rejestrów, kompilator zwykle zrobi to lepiej)

    Użycie słów "operacje assebletrowe " budzi mój sprzeciw, jest totalnie niejasne. Piszesz o kodzie ręcznym? Wygenerowanym automatycznie?

    WX3V napisał:

    Zatem i zmienna static będzie musiała być przeniesiona do któregoś z nich. Aczkolwiek zawartość tego rejestru nie będzie chroniona czyli rejestr będzie mógł być nadpisany w następnych instrukcjach. Natomiast kolejne odwołanie (w tej samej procedurze) do takiej zmiennej będzie powodowało ponowne jej ściągnięcie z przestrzeni SRAM lub Flash i wpisanie do któregoś z rejestrów - niekoniecznie tego samego co poprzednio.
    Cóż, zwykle kilka kolejnych "przebiegów kompilacji" służy minimalizacji długości kodu wynikowego, a nie minimalizacji czasu jego wykonania. Zresztą taka funkcja celu jest zdecydowanie trudniejsza do praktycznego wykonania.


    Tu jest kilka przesmyknięć się nad faktami. M.in. najbardziej typową optymalizacją jest szybkość a nie długość kodu.
  • #14 16810486
    kamil94goldman
    Poziom 3  
    Marek_Skalski napisał:
    Jaka jest częstotliwość PWM, jaka ADC, a z jaką częstotliwością pracuje serwo?

    ADC (12 bit) pracuje w trybie freerunning, z częstotliwością próbkowania około 150 ksps, częstotliwość PWM wynosi 50 kHz, funkcja regulacji przetwornicy, czyli przerwań od timera jest z taką samą częstotliwością, co PWM, czyli 50 kHz w przerwaniach od przepełnienia timera PWM.

    Generalnie układ działa dosyć stabilnie, bez obciążenia napięcie waha się, o około 0,1 V, niekiedy 0,2. Z obciążeniem napięcie jest stabilne co do dziesiętnych części.

    Marek_Skalski napisał:
    Serwo może spokojnie pracować 7x wolniej niż PWM, a rozdzielczość PWM powinna być większa od rozdzielczości ADC.

    Czy to oznacza że funkcja regulacji może być wykonywana około 7x wolniej od częstotliwości PWM? Nie mogę za bardzo zrozumieć dlaczego. Czy układ zdąży zareagować wówczas w stanach dynamicznych?

    Marek_Skalski napisał:
    Takie sterowanie przetwornicą jest do niczego. Taki układ może bardzo łatwo zdestabilizować, ponieważ nie ma tutaj żadnego filtra/kompensatora.

    Z tym kompensatorem chodzi o to, że zmierzona wartość rzeczywista, powinna być uśredniona, za parę cykli pomiaru?

    Marek_Skalski napisał:
    Musisz też mieć odpowiedni margines fazy, inaczej układ zacznie się wzbudzać, albo będzie bardzo leniwie reagować na zmiany obciążenia.

    Co to oznacza margines fazy? nie rozumiem tego za bardzo, ani nigdzie specjalnie nie mogę znaleźć.
  • Pomocny post
    #15 16810716
    Konto nie istnieje
    Poziom 1  
REKLAMA