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

AVR ATmega32: switch/case vs if - optymalizacja szybkości programu

pgp 31 Mar 2006 22:20 6133 13
REKLAMA
  • #1 2480076
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Mam problemy z szybkościa działania programu na AVR ATmega 32. CZy lepiej używa cinstrukcji switch/case :

    switch(x)
    {
    case 0x04: pozmen1--; //jak tutaj damy -- to się zamota bo typ unsigned jest !
    break;
    case 0x03: pozmen1++;
    break;
    case 0x02: warstwa++; //we
    break;
    case 0x01: warstwa--; // wy
    break;

    }

    czy lepiej if-ów :

    if(x==0x04) pozmen1--; //jak tutaj damy -- to się zamota bo typ unsigned jest !
    if(x==0x03) pozmen1++;
    if(x==0x01) warstwa--; // wy
    if(x==0x02) warstwa++; //we


    jakie sa wasze spostrzeżenia co do różnicy szybkosci chodzenia programów ? Bo ja w swoim mam raz switche, raz casy, w zależności jak mo wygodnie...
  • REKLAMA
  • #2 2480311
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    W tym przypadku case będzie zawsze szybszy, bo od razu odrzuca pozostałe przypadki. Wydaje mi się że kod dla case i napisany przy pomocy IF tak jak poniżej będzie bardzo podobny:
    if (x==0) .....
    else if (x==1) ....
    else if (x==2) ....

    Ale tak naprawde wszystko zalezy od tego jak "inteligentny" jest kompilator.
  • REKLAMA
  • #3 2480761
    greg_matrix
    Poziom 17  
    Posty: 163
    Pomógł: 28
    Ocena: 3
    Taki "multi-If" będzie działał z różną szybkością. To zalezeży ile warunków będzie trzeba sprawdzić po drodze żeby odrzucić pozostałe- to się będzie zmieniało właśnie w zależności od wartości X. Tak więc pewnie "Select case".
  • REKLAMA
  • #4 2481661
    Ireq
    Poziom 13  
    Posty: 56
    Pomógł: 1
    Ocena: 1
    Mi osobiscie wygodniej jest uzywac If'ow ale szybsze jest case.
  • #5 2482011
    Warhard
    Poziom 12  
    Posty: 109
    Pomógł: 1
    Ocena: 1
    Zdecydowanie "if-ów" . Dlatego iż jednak zawsze ta instrukcja bedzie szybsza niż case oraz kod wynikówy programu bedzie mniejszy - może nie dużo ale zawsze - w mikroprocesorkach nieraz jest to bardzo istotne gdy mamy do dyspozycji kilka kilo.
    Co do instrukcji "if' używać samo "if" bez "else" - jeśli jest potrzebne "else" użyć dwóch instrukcji "if"
  • REKLAMA
  • #6 2482453
    migod
    Poziom 21  
    Posty: 462
    Pomógł: 29
    Ocena: 8
    Warhard, jestes pewny co do tego ostatniego -seria if-ow bez else ma byc Twoim zdaniem szybsza..? nie bardzo znajduje uzasadnienie dla takie tezy..

    wtedy przy serii 5-ciu warunkow w pierwszym przypadku sprawdza sie srednio 2.5 razy warunki, w drugim przypadku (najoptymistyczniej) 5-ciokrotnie. gdzie jest zysk?

    aa, i jesli juz tak stroic wydajnosc, to dobrze jest pomyslec chwile i ustalic wlasciwa (statystycznie) kolejnosc sprawdzania warunkow, aby ich srednia liczba byla mozliwie najmniejsza.
    kompilator tego za nas nie zrobi, chociaz nie jestem pewny, czy jego algorytmy optymalizacyjne nie zaburza naszego "porzadku" ;-)

    switch powinien byc szybszy (nowoczesne kompilatory nie wygeneruja raczej przy nich nieefektywnego kodu).

    pozdro,
    --
    migod
  • #7 2484025
    ko_rex
    Poziom 19  
    Posty: 253
    Pomógł: 38
    Ocena: 2
    Drodzy Panowie! Przecież nie ma w żadnym procku instrukcji, która sprawdza od razu 5 warunków! Żeby zrealizować switch'a trzeba kolejno sprawdzić warunki a potem ewentualnie gdzieś skoczyć, więc sprawa sprowadza się do tego samego co w if'ie.

    Takie moje skromne spostrzeżenie...

    No..co prawda jest metoda do szybkiego realizowania switch'y... na podstawie wartości zmiennej, od której zależy sekwencja case'ów, wylicza się adres, pod który sie skacze i gotowe (zeby to miało sens robi sie dwa skoki, pierszy na podstawie zmiennej do instrukcji właściwego, czyli drugiego skoku).
    Pytanie tylko: Który kompilator to wykorzystuje? CVAVR nie.
  • #8 2484652
    h0nza
    Poziom 15  
    Posty: 85
    Pomógł: 7
    Ocena: 9
    A więc co do długości kodu każdy może sam ocenić same ify zajmują najmniej ale switch case jest chyba najszybsze (biorąc pod uwagę że spełniony będzie warunek a=4;


    ; SAME IF'Y

    ; if(a==1)b++;
    MOV A,a?040
    CJNE A,#01H,?C0001
    INC b?041
    ?C0001:
    ; if(a==2)c++;
    MOV A,a?040
    CJNE A,#02H,?C0002
    INC c?042
    ?C0002:
    ; if(a==3)b--;
    MOV A,a?040
    CJNE A,#03H,?C0003
    DEC b?041
    ?C0003:
    ; if(a==4)c--;
    MOV A,a?040
    CJNE A,#04H,?C0004
    DEC c?042
    ?C0004:

    ; TUTAJ SĄ IF'Y I ELSE

    ; if(a==1)b++;
    MOV A,a?040
    CJNE A,#01H,?C0005
    INC b?041
    SJMP ?C0006
    ?C0005:
    ; else if(a==2)c++;
    MOV A,a?040
    CJNE A,#02H,?C0007
    INC c?042
    SJMP ?C0006
    ?C0007:
    ; else if(a==3)b--;
    MOV A,a?040
    CJNE A,#03H,?C0009
    DEC b?041
    SJMP ?C0006
    ?C0009:
    ; else if(a==4)c--;
    MOV A,a?040
    CJNE A,#04H,?C0006
    DEC c?042
    ?C0006:

    ; SWITCH I CASE

    ; switch(a){
    MOV A,a?040
    ADD A,#0FEH
    JZ ?C0014
    DEC A
    JZ ?C0015
    DEC A
    JZ ?C0016
    ADD A,#03H
    JNZ ?C0018
    ; case 1:
    ?C0013:
    ; b++;
    INC b?041
    ; break;
    SJMP koniec
    ; case 2:
    ?C0014:
    ; c++;
    INC c?042
    ; break;
    SJMP koniec
    ; case 3:
    ?C0015:
    ; b--;
    DEC b?041
    ; break;
    SJMP konec
    ; case 4:
    ?C0016:
    ; c--;
    DEC c?042
    ; break;
    ; default:;
    ; }
    ;
  • #9 2485718
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    h0nza napisał:

    ; SWITCH I CASE
    ; switch(a){
    MOV A,a?040
    ADD A,#0FEH
    JZ ?C0014
    DEC A
    JZ ?C0015
    DEC A
    JZ ?C0016
    ADD A,#03H
    JNZ ?C0018
    ; case 1:
    ?C0013:
    ; b++;
    INC b?041
    ; break;
    SJMP koniec
    ; case 2:
    ?C0014:
    ; c++;
    INC c?042
    ; break;
    SJMP koniec
    ; case 3:
    ?C0015:
    ; b--;
    DEC b?041
    ; break;
    SJMP konec
    ; case 4:
    ?C0016:
    ; c--;
    DEC c?042
    ; break;
    ; default:;
    ; };
    Troche cienki ten kompilator, większość kodów "switch/case" jakie widziałem była zbudowana w ten sposób że kod "wylicza sobie" PC na podstawie ofsetu oraz "numeru opcji" (pomnożonego przez stały współczynnik-długość instrukji), wpisuje wartość do PC, pod tym adresem znajduje się rozkaz JUMP, JMP, czy BRA który prowadzi do właściwej procedury. Nie wnikałem nigdy w implementacje na AVR, ale widziałem powyższy algorytm w programach pisanych (raczej w C) na procesory PIC oraz 51.
  • #10 2485885
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Ja jestem Ciekawy takim razie co to za kompilator taki kod wygenerowal. Mam nadzieje ze nie GCC :>
  • #11 2489475
    h0nza
    Poziom 15  
    Posty: 85
    Pomógł: 7
    Ocena: 9
    Keil 6.23a na mcs51

    aczkolwiek panie elektryk proszę zwrócić uwagę że jeżeli miałbym warunki
    case 0:
    case '@': (chyba 64 ascii)
    case 255:
    to takie odsyłanie za pomocą funkcji jmp @a+dptr by nie działało poprawnie nie pokrywając całego zakresu - a ja korzystam z instrukcji switch case np przy wczytywaniu znaków z portu szeregowego
  • #12 2493149
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    h0nza napisał:
    aczkolwiek panie elektryk proszę zwrócić uwagę że jeżeli miałbym warunki
    case 0:
    case '@': (chyba 64 ascii)
    case 255:
    to takie odsyłanie za pomocą funkcji jmp @a+dptr by nie działało poprawnie nie pokrywając całego zakresu - a ja korzystam z instrukcji switch case np przy wczytywaniu znaków z portu szeregowego
    Już kompilator o to zadba żeby było poprawnie, podczas analizu kilku programów napotkałem na takie sekwencje jumpów (do któych wcześniej prowadziło jmp @a+dptr), w których bardzo wiele instrukcji wykonywało skok pod jeden adres. Oczywiście jeśli kompilator jest odpowiednio mądry może coś jeszcze wymyśleć i wybrać "lepszą" taktyke do tego samego działania.
  • #13 2493434
    h0nza
    Poziom 15  
    Posty: 85
    Pomógł: 7
    Ocena: 9
    Zgadza się ważne jest to że działa i to znacznie szybciej niż w Bascomie
    a jak komuś zależy na prędkości zawsze można w asm'iw trochę napisać
  • #14 2901510
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Zakończając temat przychylę się do wypowiedzi kolegów stwierdzając ze wszystko zależy od tego jak kompilator przetłumaczy nasz kod...

Podsumowanie tematu

✨ Dyskusja dotyczy optymalizacji szybkości działania programu na mikrokontrolerze AVR ATmega32, a konkretnie porównania wydajności instrukcji switch/case i if. Wskazano, że switch/case może być szybszy, ponieważ pozwala na natychmiastowe odrzucenie pozostałych przypadków, jednak wiele zależy od inteligencji kompilatora. W praktyce kod if-else może być podobny do switch/case, ale szybkość działania if zależy od kolejności sprawdzanych warunków i ich liczby. Niektórzy uczestnicy podkreślają, że switch/case jest często implementowany przez kompilatory jako skok do adresu obliczanego na podstawie wartości zmiennej, co może przyspieszyć wykonanie, choć nie wszystkie kompilatory (np. CVAVR) to wykorzystują. Przykłady kodu asemblerowego pokazują różnice w generowanym kodzie dla if, if-else i switch/case. Wskazano również, że w mikrokontrolerach o ograniczonych zasobach rozmiar kodu może mieć znaczenie, a if może generować mniejszy kod. Ostatecznie podsumowano, że wybór między switch/case a if zależy od konkretnego kompilatora i sytuacji, a dla maksymalnej wydajności można stosować kod asemblerowy.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA