www.mikrocontroller.net

Forum: Compiler & IDEs Programmspeicher Verbrauch


Autor: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin Einsteiger in AVR GCC (sonst arbeite ich mit ASM) und habe heute das 
erste C Programm mit AVR GCC geschrieben. Hatte keine Probleme mit dem 
Compiler, läuft alles super, aaaaber im Build-Fenster steht:

2316 bytes (7.1% full)
(.text + .data + .bootloader)

Das kann doch wohl nicht sein, dass diese popelige Progrämmle (siehe 
unten)bereits 7% von einem ATmega32 auffrist.

Kann mir da einer weiterhelfen, was ich hier definitiv falsch gemacht 
habe.

Beste Grüße
Manni

/**************************************************************

Test Routine for fast atan2 function

 **************************************************************/

#include "main.h"

double fast_atan2 (double y, double x);

#define   PIBY2    M_PI / 2

int main( void )
  {
  double    u, x, y, z1, z2;

  x = 1.25678;
  y = 1.25678;
  z1 = atan2 (y, x);
  z2 = fast_atan2 (y, x);
  }
/**************************************************************
 Here's another atan2 function, based on a 50-year old atan
 approximation due to Hastings.
 It has an |error| < 0.005, and is 3-5x faster than atan2.
 **************************************************************/
double fast_atan2 (double y, double x)
  {
  double    atan;
  double    z;

  if (x == 0.0f)
    {
    if (y > 0.0) return PIBY2;
    if (y == 0.0) return 0.0;
    return -PIBY2;
    }

  z = y/x;
  if (fabs(z) < 1.0f)
    {
    atan = z/(1.0 + 0.28*z*z);
    if (x < 0.0)
      {
      if (y < 0.0) return atan - M_PI;
      return atan + M_PI;
      }
    }
  else
    {
    atan = PIBY2 - z/(z*z + 0.28);
    if (y < 0.0) return atan - M_PI;
    }
  return atan;
  }

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manni wrote:

> Das kann doch wohl nicht sein, dass diese popelige Progrämmle (siehe
> unten)bereits 7% von einem ATmega32 auffrist.


Na dann möchte ich Dich mal sehen, wie Du Dir in Assembler einen mit 
Floating Point Zahlen abbrichst.

Wenn Du auf weniger Code kommst und auch alles richtig rechnet, dann 
kann ich  nur sagen "Hut ab !".


Peter

Autor: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

ja das ist ja der Grund, warum ich für diesen Fall den Assembler 
verlassen hab, weil ich mir diesen Hut nicht anziehen will (hab' 
gelegentlich auch noch was anderes zu tun).

Aber erklären kann ich mir noch nicht. Wenn ich den Disassembler 
einschalte/ansehe, sind nur ca. 5% des Codes auf das Programm bezogen. 
Nach der Anweisung:

return atan

folgen noch 95% code mit der bemerkung: -----No Source-------------

Hier unten eine kurze Kopie. Habe ich etwa die ganze libm.a 
miteingebunden ?







57:         return atan;
+000001DB:   8589        LDD     R24,Y+9          Load indirect with 
displacement
+000001DC:   859A        LDD     R25,Y+10         Load indirect with 
displacement
+000001DD:   85AB        LDD     R26,Y+11         Load indirect with 
displacement
+000001DE:   85BC        LDD     R27,Y+12         Load indirect with 
displacement
+000001DF:   8B89        STD     Y+17,R24         Store indirect with 
displacement
+000001E0:   8B9A        STD     Y+18,R25         Store indirect with 
displacement
+000001E1:   8BAB        STD     Y+19,R26         Store indirect with 
displacement
+000001E2:   8BBC        STD     Y+20,R27         Store indirect with 
displacement
58:         }
+000001E3:   8969        LDD     R22,Y+17         Load indirect with 
displacement
+000001E4:   897A        LDD     R23,Y+18         Load indirect with 
displacement
+000001E5:   898B        LDD     R24,Y+19         Load indirect with 
displacement
+000001E6:   899C        LDD     R25,Y+20         Load indirect with 
displacement
+000001E7:   9664        ADIW    R28,0x14         Add immediate to word
+000001E8:   B60F        IN      R0,0x3F          In from I/O location
+000001E9:   94F8        CLI                      Global Interrupt 
Disable
+000001EA:   BFDE        OUT     0x3E,R29         Out to I/O location
+000001EB:   BE0F        OUT     0x3F,R0          Out to I/O location
+000001EC:   BFCD        OUT     0x3D,R28         Out to I/O location
+000001ED:   91DF        POP     R29              Pop register from 
stack
+000001EE:   91CF        POP     R28              Pop register from 
stack
+000001EF:   9508        RET                      Subroutine return
+000001F0:   5850        SUBI    R21,0x80         Subtract immediate
+000001F1:   2E19        MOV     R1,R25           Copy register
+000001F2:   D103        RCALL   PC+0x0104        Relative call 
subroutine
+000001F3:   D001        RCALL   PC+0x0002        Relative call 
subroutine
+000001F4:   C0E6        RJMP    PC+0x00E7        Relative jump
+000001F5:   17BA        CP      R27,R26          Compare
+000001F6:   0762        CPC     R22,R18          Compare with carry
+000001F7:   0773        CPC     R23,R19          Compare with carry
+000001F8:   0784        CPC     R24,R20          Compare with carry
+000001F9:   0795        CPC     R25,R21          Compare with carry
+000001FA:   F1B1        BREQ    PC+0x37          Branch if equal
+000001FB:   F488        BRCC    PC+0x12          Branch if carry 
cleared
+000001FC:   F40E        BRTC    PC+0x02          Branch if T flag 
cleared
+000001FD:   9410        COM     R1               One's complement
+000001FE:   2E0B        MOV     R0,R27           Copy register
+000001FF:   2FBA        MOV     R27,R26          Copy register
+00000200:   2DA0        MOV     R26,R0           Copy register
+00000201:   2E06        MOV     R0,R22           Copy register
---- No Source 
------------------------------------------------------------------------ 
------------
+00000202:   2F62        MOV     R22,R18          Copy register
+00000203:   2D20


und  hier kommen noch ca. 1800 bytes.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gleitkommabibliothek eben.

Autor: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, verstehe ich !

Dann muss ich mal weiter forschen, wie ich das atan2 Problem anders 
lösen lösen kann. Hab's mittlerweile auch im Disassembler gesehen, eben 
die Gleitkommabibliothek.

Danke Dir !

Autor: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg
Hab's gerade erst bemerkt: ist DL8DTL dein AFU Kennzeichen ? Würde mich 
wundern, da am Ende ein Zeichen zuviel.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie Peter schon schrieb, wird es dir sicher schwer fallen, Gleitkomma-
arithmetik in anderer Form mit wesentlich weniger Speicherverbrauch zu
implementieren.

Eventuell beschreibst du ja lieber mal dein Problem.

Ja, DL8DTL ist das Afu-Rufzeichen.  Suffixe mit 1 Ziffer und 3
Buchstaben sind doch durchaus gängig, und waren praktisch die
einzigen, die sie uns seinerzeit hier in Neufünfland übergeholfen
haben, als wir unsere Y2-Calls abgeben mussten (obwohl die BRD ja nach
wie vor auf dem Block Y2-Y9 gluckt -- man hätte sie also auch
,,biologisch ausklingen'' lassen können, wenn man gewollt hätte).
Suffixe mit nur zwei Buchstaben oder das Rückerlangen alter DM-Calls
wurden erst später möglich.  Aber letzteres hatte ich (gerade so)
ohnehin nicht mehr besessen, und außerdem hätte es noch einen Wechsel
des Calls bedeutet, das macht man nicht freiwillig.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du jetzt noch deine Fliesskommazahlen über uart per printf 
ausgibst, kommt nochmals ein dicker Speicherhappen dazu. Das war es dann 
aber auch. Alles, was du dann noch anstellst, wird die Codegröße 
ungefähr linear anwachsen lassen, und das auch im erwarteten Rahmen. Da 
ist noch viel Platz im Flash.

Das Compilerflag -Os ist aber immer hilfreich.

Oliver

Autor: Manni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Oliver:
na das hat's ja ordentlich gebracht: ca. 47% weniger Programm-Bytes. 
Habe aber noch nicht ausprobiert, was der Einfluß auf's Timing ist: 
Zitat User Manual: "... at the possible expense of code execution 
speed".

@Jörg:
Danke dir für die Eräuterungen zu deinem Rufzeichen. Bin ein bischen aus 
der Übung gekommen weil mein 3-Element Beam nach dem Umzug in 2004 noch 
immer im Keller liegt. Diesen Sommer kommt sie aber wieder auf's Dach.
Gruß DK4GL

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"... at the possible expense of code execution speed". Das mag im 
PC-Umfeld, im Vergleich zu der Optimierungsstufe -O3 stimmen.

Das schöne bei den Atmels ist, daß ein Befehl nur einen Takt dauert (die 
allermeisten jedenfalls). Weniger Befehle => schneller. Und zwar fast so 
viel, wie der Code kleiner wird.

Oliver

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, -O3 macht zuweilen durch loop unrolling, function inlining und
solche Dinge wirklich ein paar Takte gut trotz größeren Codes, aber
in der Tendenz stimmt es schon: beim AVR ist kleinerer Code oftmals
auch schneller.

Autor: Manni (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg:
"Eventuell beschreibst du ja lieber mal dein Problem."

Anbei das "Problem", was aber eigentlich gar keines ist, bzw. sein 
sollte. Nix aufregendes mit einer Abtastrate von ca. 1 Hz. 
Phasenauflösung soll so bei einem Grad liegen. Da kann man noch vieles 
nebenbei rechnen lassen. Lookup-Table wäre auch möglich mit 2*360 10bit 
Werten (also 720 bytes). Hab ich aber noch nicht weiter verfolgt. 
Vielleicht ist das ja die einfachste Lösung.

"-O3": Bei allen verfügbaren compiler flags -O1 bis -Os kommt ungefähr 
immer die gleiche Codelänge raus, d.h. 40-50% weniger als bei -O0.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, Lookup-Tabelle oder stützpunktbasierte Interpolation, das Ganze
möglichst im Integer-Bereich.

Andererseits ist die Frequenz wahrscheinlich wirklich gering genug,
dass du alle Zeit der Welt zum Rechnen hast, und Programmspeicher
hast du auch noch reichlich.  Wenn's die Entwicklung des Prototypen
schneller macht, ist also die Gleitkommarechnung vielleicht gar nicht
so fehl am Platz.  Wenn sie's am Ende ohne Einschränkung tut, warum
solltest du sie nicht auch einfach benutzen?  Schließlich wirst du
von Atmel kein Geld zurück bekommen, wenn du Teile des ROMs nicht
benutzt. ;-)

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.