Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller: Codeoptimierung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Leonhard (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
1
// Time: Datentyp unsigned long
2
// Tick: Datentyp uint64_t
3
// CYCLE = 500
4
5
// Zeitdifferenz
6
unsigned long difference = (unsigned long)((Tick*CYCLE)/(double)1000 - Time);
1
Time = (unsigned long)((Tick*CYCLE)/(double)1000);

Die Variable Tick wird in einer Timerroutine jede 500ms um einen Wert 
hochgezählt --> Tick++

Wie könnten die beiden oberen Ausdrucke optimiert werden?

von Stampede (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Integer und keine Floats oder Double nutzen.

von Leonhard (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Könnte die auch mit einer Schiebeoperation optimiert werden?

von Nico W. (nico_w)


Bewertung
0 lesenswert
nicht lesenswert
Warum wird die 1000 auf double gecastet?
Kann man CYCLE nicht so skallieren, dass man anstatt 1000, 1024 nimmt um 
zu schieben?

von Leonhard (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich brauche die Werte in Sekunden

von Irgendwer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
unsigned long Time_vorher = Time;
Time = (unsigned long)(Tick>>1); // entspricht Tick/2
unsigned long difference = Time - Time_vorher;
...

von Random .. (thorstendb) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Scaled int.
Du speicherst 1sec als 10/100 (bedingt durch deine Genauigkeit von 
500ms) in der Variable, hochzählen dann als +5 (entspricht 5/100).

von Sebastian K. (sek)


Bewertung
0 lesenswert
nicht lesenswert
Mein erster Ansatz wäre:
500 / 1000 = 1/2

Entspricht einem Shift nach rechts

von Random .. (thorstendb) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Anm.:
10/100 = 10 hundertstel

Um shift operationen zu verwenden, musst du auf unsigned int gehen. Mit 
signed geht das nur begrenzt, mit double gar nicht.

von Peter D. (peda)


Bewertung
1 lesenswert
nicht lesenswert
Dem MC ist es schnurz, ob die Zeitbasis exakte Sekunden zählt. Rechne 
einfach intern immer nur in Ticks und erst ganz zum Schluß für die 
Ausgabe für den Menschen in Sekunden um.
Und um zu vergleichen, ob eine bestimmte Zeit abgelaufen ist, rechne sie 
einmalig in Ticks um und vergleiche die Ticks.

von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Dass du in FLoating-Point rechnen lässt, deutet darauf hin, dass der
Mikrocontroller eine FPU hat, die ähnlich schnell rechnet wie die
Integer-Einheit.

Du kannst aus den zwei Operationen eine machen, indem du statt

1
(Tick*CYCLE)/(double)1000

dieses

1
Tick * (CYCLE / (double)1000)

oder einfach dieses

1
Tick * (CYCLE / 1000.0)

schreibst. Der Compiler führt dann die Division bereits zur Compile-Zeit
aus.

: Bearbeitet durch Moderator
von THOR (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Dass du in FLoating-Point rechnen lässt, deutet darauf hin, dass
> der
> Mikrocontroller eine FPU hat, die ähnlich schnell rechnet wie die
> Integer-Einheit.

Und die Existenz dieses Threads sagt mir, dass das Gegenteil der Fall 
ist.

von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Noch etwas:

Da Tick nur alle 500ms hochgezählt wird, brauchst du dir an dieser
Stelle bzgl. Laufzeitoptimierung keine Gedanken machen. Oder geht es um
die Optimierung der Programmgröße?

von W.S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Leonhard schrieb:
> Die Variable Tick wird in einer Timerroutine jede 500ms um einen Wert
> hochgezählt --> Tick++
>
> Wie könnten die beiden oberen Ausdrucke optimiert werden?

Indem man sie einfach wegläßt. Ich frage mich bloß, wer auf die Idee 
kommt, für eine interne Uhr auf Basis von 0.5 Sekunden einen unsigned 
int64 benutzen zu wollen. Das würde vermutlich ausreichen, bis unsere 
Sonne verglüht ist.

Wenn man das Ganze mit einem simplen 32 Bit Wort erledigt, dann reicht 
das immer noch für 2 Milliarden Sekunden, man spart sich das 64 Bit 
Rechnen und dort mit einem Gleitkommaformat arbeiten zu wollen ist 
obendrein unangebracht.

Warum nur kommen die Leute nicht darauf, mal zu überlegen, wofür welche 
Datenbreite eigentlich ausreichen würde? Ist das eine Folge der 
Einführung von uint64_t und Konsorten, daß über Datenlängen nicht mehr 
nachgedacht wird? So nach dem Motto "Hauptsache, ich benutze stdint.h, 
dann kann mir nichts mehr passieren und ich bin immer auf der sicheren 
Seite ohne noch drüber nachdenken zu müssen". OK, ist ja auch ein 
Standpunkt - aber was für einer!

W.S.

von c.m. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
W.S. schrieb:

> Wenn man das Ganze mit einem simplen 32 Bit Wort erledigt, dann reicht
> das immer noch für 2 Milliarden Sekunden,

wenn ich richtig gerechnet habe, wären das 63 jahre bis zum überlauf.


> Warum nur kommen die Leute nicht darauf, mal zu überlegen

altbekanntes problem.
das ist jetzt gar nicht mal böse gemeint, sondern resignierend 
festgestellt.

von THOR (Gast)


Bewertung
0 lesenswert
nicht lesenswert
W.S. schrieb:
> Indem man sie einfach wegläßt. Ich frage mich bloß, wer auf die Idee
> kommt, für eine interne Uhr auf Basis von 0.5 Sekunden einen unsigned
> int64 benutzen zu wollen. Das würde vermutlich ausreichen, bis unsere
> Sonne verglüht ist.

292 Mrd. Jahre wenn ich mich nicht verrechnet habe. Also sogar noch 
deutlich länger :)

von Nico W. (nico_w)


Bewertung
0 lesenswert
nicht lesenswert
c.m. schrieb:
> wenn ich richtig gerechnet habe, wären das 63 jahre bis zum überlauf.

68 Jahre bei 32bit und 2 Ticks pro Sekunde.

Bei 64bit sind 292 mrd. Jahre. Nur als Vergleich. Das Universum ist grob 
13.8 mrd. Jahre jung.

von THOR (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Halt, 585 Mrd. Jahre.

von THOR (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Nico W. schrieb:
> Bei 64bit sind 292 mrd. Jahre. Nur als Vergleich. Das Universum ist grob
> 13.8 mrd. Jahre jung.

Das sind 2^64. Aber die anderen Bits können ja auch alle 1 sein, sind 
also 2^65-2. Das ist der Wertebereich eines uint64.

von Nico W. (nico_w)


Bewertung
0 lesenswert
nicht lesenswert
THOR schrieb:
> 2^65-2. Das ist der Wertebereich eines uint64.

Nö.

von Nop (Gast)


Bewertung
1 lesenswert
nicht lesenswert
W.S. schrieb:

> Das würde vermutlich ausreichen, bis unsere Sonne verglüht ist.

Und dann ist der Akku eines Nokia 3310 immer noch halb voll.

> Ist das eine Folge der Einführung von uint64_t und Konsorten

Nö. Vorher hieß der Algorithmus
- füge soviele 'long' ein, wie der Compiler noch nicht meckert.
- freue Dich, daß Du dann immer noch nicht auf Anhieb siehst, wie breit 
der Datentyp ist, aber sicher sein kannst, daß es ausreicht.

Alternativ dazu kann man übrigens auch mit int32_t arbeiten und Ticks 
zählen. Boeing hatte da vor zwei Jahren im 787 Spaß mit einem 
Generatorcontroller, der das mit Ticks von 10ms so gemacht hat. "Bitte 
rebooten Sie dieses Flugzeug alle 248 Tage".

von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
THOR schrieb:
> 292 Mrd. Jahre wenn ich mich nicht verrechnet habe. Also sogar noch
> deutlich länger :)

Obacht:

Die Multiplikation mit CYCLE=500 darf keinen Überlauf verursachen. Du
musst du die berechnete Zeitdauer also noch durch 500 dividieren und es
verbleiben nur noch 584 Mio. Jahre. So lange wird die Sonne ziemlich
sicher noch scheinen. Der TE hätte also besser ein 128-Bit-Integer
genommen. Mit nur 32 Bit wäre sogar schon nach knapp 50 Tagen Ende ;-)

Aber wahrscheinlich hat der TO unter den vielen Vorschlägen schon den
passenden ausgewählt. Wenn nicht, sollte er vielleicht erst einmal
folgende Fragen beantworten:

- Um welchen Mikrocontrollertyp geht es?

- Was genau soll optimiert werden (Laufzeit, Speicher, Größe des
  Quellcodes oder was auch immer)?

- Falls Laufzeit: Muss bei bei 0,5s Zykluszeit überhaupt etwas optimiert
  werden?

- Braucht man diese (aus Sicht des Mikrocontrollers) "krumme" Skalierung
  überhaupt?

von W.S. (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Die Multiplikation mit CYCLE=500 darf keinen Überlauf verursachen. Du
> musst du die berechnete Zeitdauer also noch durch 500 dividieren und es
> verbleiben nur noch 584 Mio. Jahre.

Was ist denn heut mit dir los?

Also, lies das mal GRÜNDLICH:

Leonhard schrieb:
> Die Variable Tick wird in einer Timerroutine jede 500ms um einen Wert
> hochgezählt --> Tick++

Eben.

In der Timer-Routine steht ein simples Inkrementieren eines unsigned 
int64 und das passiert alle 0.5 Sekunden.

Von was für einer Multiplikation redest du? Von einer völlig 
überflüssigen etwa? Wer die verflossenen Sekunden wissen will, teilt 
Tick durch zwei oder schiebt ihn um 1 Bit nach rechts und fertig ist die 
Laube.

Wer die Minuten wisen will, muß das dann durch 60 teilen .. na und so 
weiter. Dieser Kruscht mit "(unsigned long)((Tick*CYCLE)/(double)1000);" 
war von Anfang an völliger Mumpitz.

W.S.

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]
  • [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.