mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik gezielte Optimierung einzelner Funktionen mit gcc?


Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Gibt es eine Möglichkeit den gcc dazu zu bringen einzelne Funktion mit 
Os und andere mit O3 zu kompilieren?

Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den 
Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash, bei 
dem eher unkritischen Hauptprogramm versucht man Platz zu sparen.

Grüße
Robert

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert B. schrieb:

> Gibt es eine Möglichkeit den gcc dazu zu bringen einzelne Funktion mit
> Os und andere mit O3 zu kompilieren?

Ja.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
>
> Ja.

Wie?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, das ist ja schick. Gibt's aber auch noch nicht so lange, oder?

Ansonsten kann man natürlich auch einfach die Funktionen, die andere 
optimierungs-Einstellungen brauchen, in eine eigene .c-Datei (oder 
mehrere) stecken und diese mit den speziellen Einstellungen übersetzen.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, schade, so gehts nicht:

__attribute__((optimize("O3"))) ISR(TIMER1_COMPA_vect)
{
...
}

führt zu

warning: 'optimize' attribute directive ignored

Ein testweises "const" (was quatsch ist) läuft durch. Die Schreibweise 
O3 -O3 3 etc. habe ich schon versucht.

Grüße
Robert

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte sein, dass dies erst ab 4.4 geht. Bei den Pragmas steht das so 
explizit drin.

Allerdings kann es auch sein, dass der Makro ISR() mitmischt. Muss man 
genauer ansehen, was dabei hinten aus dem Präprozessor rauskommt. Ggf. 
ist auch
   function-declaration __attribute___(...) { ... }
also Attribute dahinter der richtige Weg.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Scheint so, denn unter 
http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Functi... 
wird dieses Attribut nicht erwähnt.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert B. schrieb:
> Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den
>
> Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash,

Schlechtes Beispiel. ISR's, besonders zeitkritische, sind (bzw. sollten) 
so kurz sein, daß da die verschiedenen Optimierungsstufen gar keinen 
Unterschied machen.

Und im Falle des avr-gcc ist -O3 sowieso zweckfrei. Ernsthaft schneller 
als mit -Os wird es damit nicht. Als Risk-Prozessor mit einem (oder 
zwei) Zyklen pro Befehl gilt beim AVR kurz = schnell.

Oliver

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Scheint so, denn unter
> http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Functi...
> wird dieses Attribut nicht erwähnt.

Ja, hab's gerade ausprobiert: 4.4.2 unterstützt das Attribut, 4.3.4 und
4.2.4 nicht.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Robert B. schrieb:
>> Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den
>>
>> Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash,
>
> Schlechtes Beispiel. ISR's, besonders zeitkritische, sind (bzw. sollten)
> so kurz sein, daß da die verschiedenen Optimierungsstufen gar keinen
> Unterschied machen.
>
> Und im Falle des avr-gcc ist -O3 sowieso zweckfrei. Ernsthaft schneller
> als mit -Os wird es damit nicht. Als Risk-Prozessor mit einem (oder
> zwei) Zyklen pro Befehl gilt beim AVR kurz = schnell.
>
> Oliver

-Os
  if (tmp_vel > 0) {
     722:  14 16         cp  r1, r20
     724:  1c f4         brge  .+6        ; 0x72c <__vector_11+0xa2>
    act_pos_buf++;
     726:  cb 01         movw  r24, r22
     728:  01 96         adiw  r24, 0x01  ; 1
     72a:  02 c0         rjmp  .+4        ; 0x730 <__vector_11+0xa6>
  } else {
    act_pos_buf--;
     72c:  cb 01         movw  r24, r22
     72e:  01 97         sbiw  r24, 0x01  ; 1
  }

-O3
  if (tmp_vel > 0) {
     7b2:  14 16         cp  r1, r20
     7b4:  0c f0         brlt  .+2        ; 0x7b8 <__vector_11+0xae>
     7b6:  46 c0         rjmp  .+140      ; 0x844 <__vector_11+0x13a>
    act_pos_buf++;
     7b8:  cb 01         movw  r24, r22
     7ba:  01 96         adiw  r24, 0x01  ; 1
  } else {
    act_pos_buf--;
  }
...
  if (tmp_vel > 0) {
    act_pos_buf++;
  } else {
    act_pos_buf--;
     844:  cb 01         movw  r24, r22
     846:  01 97         sbiw  r24, 0x01  ; 1
     848:  b9 cf         rjmp  .-142      ; 0x7bc <__vector_11+0xb2>
  }

das mit avr-gcc 4.3.3

Keine Ahnung warum der gcc bei -O3 einen Code dermaßen zerrupft - super 
unschön. Zumal mit schlechter lesbarer Nachhilfe die Optimierung viel 
besser ist:

-O3 / Os
  act_pos_buf--;
     7b2:  cb 01         movw  r24, r22
     7b4:  01 97         sbiw  r24, 0x01  ; 1
  if (tmp_vel > 0) {
     7b6:  14 16         cp  r1, r20
     7b8:  14 f4         brge  .+4        ; 0x7be <__vector_11+0xb4>
    act_pos_buf += 2;
     7ba:  cb 01         movw  r24, r22
     7bc:  01 96         adiw  r24, 0x01  ; 1
  }  

unverständlich warum er nicht erzeugt:
     movw   r24, r22
     sbiw   r24, 0x01
     sbrs   r20,7
     adiw   r24, 0x02

...sollte ja equivalent sein...

Grüße
Robert

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert B. schrieb:

> unverständlich warum er nicht erzeugt:
> [...]
> ...sollte ja equivalent sein...

Weil ein Compiler kein Werkzeug ist, das in jedem speziellen Einzelfall 
einen garantiert nicht weiter optimierbaren Code erzeugt. Aber es ist 
durchaus möglich, ihm das in diesem Fall beizubringen, der Quellcode ist 
öffentlich.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor allem muss ja jemand die Optimierung mal dem Compiler beigebracht 
haben.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Robert B. schrieb:
>
>> unverständlich warum er nicht erzeugt:
>> [...]
>> ...sollte ja equivalent sein...
>
> Weil ein Compiler kein Werkzeug ist, das in jedem speziellen Einzelfall
> einen garantiert nicht weiter optimierbaren Code erzeugt. Aber es ist
> durchaus möglich, ihm das in diesem Fall beizubringen, der Quellcode ist
> öffentlich.

Warum mit leicht genervten Unterton? Ist doch völlig fehl am Platz...

Ich stelle hier eine Frage rein und freue mich wenn jetzt jemand sagt 
"hilf dem Compiler so und so". Dass der Compiler nicht jeden Spezialfall 
erkennen kann (und da habe ich auch schon ein paar inline-hacks aus 
gutem Grund gemacht) ist völlig klar - bei diesem Szenario wundert es 
mich halt.

Spätestens bei dem "helfenden" C-Code sollte der Compiler doch erkennen, 
dass er nachdem er den Drecrement gemacht hat abhängig vom Vorzeichen 
nur einen einzigen Befehl überspringen oder ausführen muss.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert B. schrieb:

> Warum mit leicht genervten Unterton? Ist doch völlig fehl am Platz...

Wie es in den Wald reinruft, so schallt es zurück. Vielleicht habe ich 
deinen Anspruch "unverständlich warum er nicht erzeugt:" auch etwas 
misverstanden.

Jedenfalls ist der Code, den du als optimalen Ersatz gebastelt hat, 
nicht unbedingt typisch für den Output eines Compilers. Es sei denn 
jemand hat ihn speziell dafür optimiert (sowas kommt gelegentlich bei 
auf spezielle Sequenzen bekannter Benchmarks optimierenden Compilern 
vor).

> Spätestens bei dem "helfenden" C-Code sollte der Compiler doch erkennen,
> dass er nachdem er den Drecrement gemacht hat abhängig vom Vorzeichen
> nur einen einzigen Befehl überspringen oder ausführen muss.

Deine Variante setzt voraus, dass beide Zweige vom "if" in Beziehung 
gesetzt werden und der Compiler erkennt, dass er die darin enthaltene 
Arithmetik aufeinander aufbauen kann, statt sie alternativ auszuführen. 
Sowas lässt sich in den Compiler einbauen, aber offenbar hat das eben 
niemand getan.

Was ich hingegen auf Architekturen mit Predication (z.B. ARM) schon 
gesehen habe ist sinngemäss sowas wie
  cmp tmp_vel, #0
  if.gt add act_pos_buf, #1
  if.le sub act_pos_buf, #1
und bei bei solchen mit bedingtem Move (x86 >= 686) findet man sowas wie
  add temp, act_pos_buf, #1
  sub act_pos_buf, #1
  cmp tmp_vel, #0
  if.gt move act_pos_buf, temp
um den oft problematischen Sprung zu vermeiden. Das sind eher generische 
Optimierungen. Das letztere allerdings liesse sich auch mit AVRs machen, 
es wird dort aber weder kürzer noch schneller.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.