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


von Robert B. (robertb)


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

von (prx) A. K. (prx)


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.

von Robert B. (robertb)


Lesenswert?

A. K. schrieb:
>
> Ja.

Wie?

von (prx) A. K. (prx)


Lesenswert?


von Rolf Magnus (Gast)


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.

von Robert B. (robertb)


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

von (prx) A. K. (prx)


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.

von Rolf Magnus (Gast)


Lesenswert?

Scheint so, denn unter 
http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Function-Attributes.html#Function-Attributes 
wird dieses Attribut nicht erwähnt.

von Oliver (Gast)


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

von Yalu X. (yalu) (Moderator)


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.

von Robert B. (robertb)


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
1
  if (tmp_vel > 0) {
2
     722:  14 16         cp  r1, r20
3
     724:  1c f4         brge  .+6        ; 0x72c <__vector_11+0xa2>
4
    act_pos_buf++;
5
     726:  cb 01         movw  r24, r22
6
     728:  01 96         adiw  r24, 0x01  ; 1
7
     72a:  02 c0         rjmp  .+4        ; 0x730 <__vector_11+0xa6>
8
  } else {
9
    act_pos_buf--;
10
     72c:  cb 01         movw  r24, r22
11
     72e:  01 97         sbiw  r24, 0x01  ; 1
12
  }

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

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
1
  act_pos_buf--;
2
     7b2:  cb 01         movw  r24, r22
3
     7b4:  01 97         sbiw  r24, 0x01  ; 1
4
  if (tmp_vel > 0) {
5
     7b6:  14 16         cp  r1, r20
6
     7b8:  14 f4         brge  .+4        ; 0x7be <__vector_11+0xb4>
7
    act_pos_buf += 2;
8
     7ba:  cb 01         movw  r24, r22
9
     7bc:  01 96         adiw  r24, 0x01  ; 1
10
  }

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

...sollte ja equivalent sein...

Grüße
Robert

von (prx) A. K. (prx)


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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Vor allem muss ja jemand die Optimierung mal dem Compiler beigebracht 
haben.

von Robert B. (robertb)


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.

von (prx) A. K. (prx)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.