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

[c]AVR-GCC optymalizacja nieużywanych procedur/funkcji?

PO. 26 Kwi 2010 21:47 4178 18
  • #1 8006630
    PO.
    Poziom 20  
    No właśnie, jak to jest? Dotychczas myślałem, że jak funkcja nigdzie nie jest wywoływana to kompilator ją sobie wywali.
    Okazało się, że jednak nie (nie zawsze? od czego to zależy?) i dzisiaj "odśmiecałem" bibloteki, żeby się zmieścić w pamięci... Biblioteka niekompilowana, w jednym pliku bez nagłówków - czy to ma jakiś wpływ?
  • #2 8006671
    tadzik85
    Poziom 38  
    Mówisz o bibliotece *.c? Jeśli chcesz wykorzystywać jej cześć tylko dobrze jest wykorzystać deklaracje extern. Albo edytować bibliotekę niestety
  • #3 8006690
    PO.
    Poziom 20  
    Znaczy co jak deklarować? W sumie pytam teoretycznie, bo zrobiłem dalszy podział biblioteki i inkluduję sobie po kawałku. Bo to jest zbiorcza do kilku projektów naraz ;) .
  • #4 8006736
    tadzik85
    Poziom 38  
    Zamiast dołączać całą bibliotekę C do projektu (do linkowania). deklarujesz sobie funkcje poprzez extern która znajduje się w innym module.
  • #5 8006872
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Tia... A jak będziesz chciał, żeby samochód mniej palił, to najlepiej zalepić ze 2-3 tłoki pianką do uszczelniania okien...

    LUDZIE! Trochę powagi! Do usuwania nieużywanych funkcji każdy kompilator ma jakieś opcje i w przypadku gcc jest to -ffunction-sections dodane do kompilacji i --gc-sections dodane do linkowania, a nie jakieś cudaczne includowanie, bo (zasadniczo) NIGDY nie includuje się kodu.

    BTW dokładnie taki sam manewr należy robić z danymi poprzez dodanie do kompilacji -fdata-sections.

    No i oczywiście włączyć optymalizację, bo po co optymalizować coś co nie jest optymalne z założenia?

    Extern dodane do deklaracji funkcji która jest dostępna w postaci kodu jest totalnym bezsensem i niczego nie zmienia! Extern używa się przy deklaracji funkcji dostępnych w bibliotekach, czyli plikach z rozszerzeniem .a, i to tylko dla czytelności, ponieważ modyfikator ten (zasadniczo) jest zbędny przy funkcjach.

    No i jak zwykle - po raz milionowy - biblioteka (rozszerzenie .a), to jest taki plik w którym znajdują się SKOMPILOWANE funkcje, zwykle pokroju printf(), sin(), itoa() itp. Plik z rozszerzeniem .c to jest najzwyklejszy kod, można najwyżej przyszpanować i nazwać go górnolotnie modułem.

    4\/3!!
  • #6 8006993
    tmf
    VIP Zasłużony dla elektroda
    Alternatywą do tego co pisze Freddie jest stworzenie biblioteki w której każda funkcja to jeden plik kompilowany jako osobna jednostka kompilacji i potem uzyskane pliki obj łączy się w bibliotekę. Kompilator wybiera tylko funkcje użyte - ale to jest odpowiednik -ffunction-sections.
  • #7 8063689
    PO.
    Poziom 20  
    No dobra, krytyka przyjęta ;) .

    Natomiast po dodaniu podanych parametrów niestety nic się nie dzieje, rozmiar przed i po dodaniu taki sam co do bajtu... Przetestowałem w kilku różnych projektach, specjalnie nawet upewniłem się czy są nieużywane funkcje w "modułach". Optymalizacja włączona na -Os. Przy buildzie nawet wypisuje na liście dodane przełączniki tylko nic z tego nie wynika.
    Co robię nie tak? (ale to lamersko brzmi...).
  • #9 8063965
    PO.
    Poziom 20  
    Komendy to za dużo powiedziane, klikam sobie w build i jedzie... Odpowiada mi czymś takim: avr-gcc -mmcu=atmega168 -Wall -gdwarf-2 -std=gnu99 -ffunction-sections -fdata-sections -Os -fsigned-char -MD -MP -MT minichrono.o -MF dep/minichrono.o.d -c ../minichrono.c

    więc niby to co miałem dodać się pojawia...

    A dodawałem w project options/custom options i potem albo w all files albo w linker options.
  • #11 8064357
    PO.
    Poziom 20  
    Przepraszam, przegapiłem wklejenie reszty linijek, jeśli o to chodzi?

    avr-gcc -mmcu=atmega168 --gc-sections -Wl,-Map=minichrono.map minichrono.o -o minichrono.elf

    avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature minichrono.elf minichrono.hex

    avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex minichrono.elf minichrono.eep || exit 0

    avr-objdump -h -S minichrono.elf > minichrono.lss


    Ewentualnie co i jak inaczej robić?
  • #12 8064436
    Freddie Chopin
    Specjalista - Mikrokontrolery
    "--gc-sections" powinno być przekazane linkerowi, a linkerowi przekazywane jest to co jest niejako "pod" flagą "-Wl", a więc powinno być mniej więcej tak:

    avr-gcc -mmcu=atmega168 -Wl,-Map=minichrono.map,--gc-sections minichrono.o -o minichrono.elf

    ew. tak:

    avr-gcc -mmcu=atmega168 -Wl,--gc-sections -Wl,-Map=minichrono.map minichrono.o -o minichrono.elf

    4\/3!!
  • #13 8065744
    PO.
    Poziom 20  
    Wychodzi na to, że muszę za rączkę :( .
    Próbowałem ręcznie w makefile dodawać linker flags ale on sobie za każdym razem zmienia makefile według tego co ma w konfiguracji. Jak to przeskoczyć?
    Wychodzi na to że pierwszy raz stało się to potrzebne...
  • #15 8065917
    PO.
    Poziom 20  
    W linker options miałem wcześniej pusto, teraz siedzi samotnie -gc-sections. Co jeszcze dodać żeby było prawidłowo...?

    PS: inaczej, może co Ty zazwyczaj masz u siebie :) ?
  • Pomocny post
    #16 8065981
    Freddie Chopin
    Specjalista - Mikrokontrolery
    przed gc-sections mają być DWA myślniki! To ważne.

    Jak jest u mnie - nie powiem Ci, bo używam Eclipse'a, a Ty pewnie AVR Studio. Zawsze możesz spróbować dopisać "-Wl,--gc-sections" - może wystarczy [;

    4\/3!!
  • #17 8066008
    PO.
    Poziom 20  
    Freddie Chopin napisał:
    przed gc-sections mają być DWA myślniki! To ważne.

    Jak jest u mnie - nie powiem Ci, bo używam Eclipse'a, a Ty pewnie AVR Studio. Zawsze możesz spróbować dopisać "-Wl,--gc-sections" - może wystarczy [;

    4\/3!!

    Tak, AVR Studio.
    Dwa myślniki były, tylko tu na forum źle wpisałem.

    Dodałem -Wl,--gc-sections i ruszyło, wielkie dzięki :) , od razu czuć różnicę.
    Kombinowałem wczoraj z dodawaniem tego -Wl ale widać w niewłaściwej kolejności.

    Czy są jeszcze jakieś inne "sztuczki" optymalizacyjne?
  • #19 16431544
    luki05
    Poziom 11  
    Odkopię temat.
    Zauważyłem że w/w optymalizacja, pokazywana w wielu źródłach nie działa do końca prawidłowo.
    Przykładowo moje opcje kompilatora
    Cytat:
    -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=8000000UL

    oraz linkera
    Cytat:
    -Wl,-Map,GSM.map -Wl,--gc-sections -mmcu=atmega8

    kod jest oczywiście optymalizowany, mniej zajmuje niż bez użycia Wl,--gc-sections, ale.....
    w momencie kiedy zakomentowałem i tak nieużywaną funkcję zajętość pamięci flash i ram pomniejszyła się.

    W takim razie, czy jest jakiś sposób, żeby faktycznie kompilator nie kompilował nieużywanych funkcji i danych?
REKLAMA