mikrocontroller.net

Forum: Compiler & IDEs Optimierung von Rechnungen und If Schleife


Autor: Manax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int choosetable(){
if(startup==1){ allticks=15000; }
uint32_t calcticks=allticks;
if (allticks >= 3191) {
  if(allticks>= 11905 ){
                     coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[0]))/1800));
               coiloff=coilon+loadtime;
             startup=0;
             return 0;
             }//253-1260
  if(allticks>= 7075  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[2]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//1261-2120
  if(allticks>= 5034  ){
              coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[3]))/1800));
              coiloff=coilon+loadtime;
              return 0;
             }//2121-2980
  if(allticks>= 3906  ){
                       coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[4]))/1800));
                  coiloff=coilon+loadtime;
             return 0;
             }//2981-3840
  if(allticks>= 3191  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[5]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//3841-4700
}else{
  if(allticks>= 2698  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[6]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//4701-5560
  if(allticks>= 2336  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[7]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//5561-6420
  if(allticks>= 2060  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[8]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//6421-7280
  if(allticks>= 1843  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[9]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//7281-8140
  if(allticks>= 1667  ){
                   coilon=allticks- 
(loadtime+((calcticks*(vorzuendung+zzp1[10]))/1800));
             coiloff=coilon+loadtime;
             return 0;
             }//8141-9000
  }
return 0;
}


Oben angefügt habe ich einen Codeabschnitt meines Programms mit dem ich 
leider so meine Probleme habe.

Die If Schleifen brauchen im Worst-case 25µs bei 20 Mhz und die Rechnung 
für den Wert coilon leider 70 µs.
Das Problem bei des Sache ist nur, dass es sich hier um eine 
zeitkritische Anwendung handelt bei der Werte für einen gesamten 
Durchlauf von 20-50 µs äußerst praktisch wären.

Gibt es Möglichkeiten den Code zu optimieren um Zeit zu sparen ?

Wenn ich oben calcticks als 16 bit Variable passiert spart es Zeit aber 
das Ergebniss wird zu ungenau. Dasselbe passiert wenn ich statt zu 
dividieren schieben um 11 benutze. Gibt es andere Möglichkeiten der 
optimierung ? Vor allem die IFs stören mich.


Bitte helft mir ich hab schon masseenhaft Foren ergebnisslos durchsucht.

mfg Manax

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

http://if-schleife.de/

auch wenn ich mir Dein Problem noch nicht genauer anegschaut habe...

Gruß aus Berlin
Michael

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte poste den Code noch einmal als Anhang, dann stimmt sowohl die 
Einrueckung als auch das Code-Highlighting und man kann ihn viel besser 
lesen.

Autor: mki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael:
lol... ist mir gar nicht aufgefallen. Jeder weis doch was er meint. Also 
jetzt sei nicht so kleinlich ;-).

Ansonsten:
Vielleicht ist eine "case-Schleife" schneller.

Autor: micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schmeiss die Division mit dem konstanten Faktor 1800 raus. Warum 
schleppst Du das mit Dir rum? Läßt sich "vorzuendung+zzp1[x]" eventuell 
im Voraus berechnen?

Autor: Route_66 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Assembler???

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann es erstmal übersichtlicher schreiben:

void choosetable( void )
{
  uint8_t idx;

  if( startup==1 )
    allticks=15000;

  switch( allticks ){
    case 11905 ... 65535: idx = 0; startup = 1; break;
    case 7057 ... 11904: idx = 2; break;
    case 5034 ... 7056: idx = 3; break;
    case 3906 ... 5033: idx = 4; break;
    case 3191 ... 3905: idx = 5; break;
    case 2698 ... 3190: idx = 6; break;
    case 2336 ... 2697: idx = 7; break;
    case 2060 ... 2335: idx = 8; break;
    case 1843 ... 2059: idx = 9; break;
    case 1667 ... 1842: idx = 10; break;
    default: return;
  }
  coilon = allticks - loadtime
  - ((uint32_t)allticks*(vorzuendung+zzp1[idx]))/1800;
  coiloff = coilon+loadtime;
}

Wenn Du mal in Worten beschreiben würdest, wozu das gut ist, könnte man 
wohl auch noch optimieren.


Peter

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> case 11905 ... 65535: idx = 0; startup = 1; break;

Man sollte sich aber bewußt darüber sein, daß das kein Standard-C, 
sondern eine Erweiterung des gcc ist.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und dass wir hier im GCC-Forum sind :-) (ack)

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das war mir schon klar, sonst hätte ich anders geantwortet. Ich find's 
nur trotzdem gut, solche Abhängigkeiten zu erwähnen.

Autor: Sauger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
>> case 11905 ... 65535: idx = 0; startup = 1; break;
>
> Man sollte sich aber bewußt darüber sein, daß das kein Standard-C,
> sondern eine Erweiterung des gcc ist.

als Pseudocode betrachten, ist lesbarer.
MfG

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manax schrieb:
> Wenn ich oben calcticks als 16 bit Variable passiert spart es Zeit aber
> das Ergebniss wird zu ungenau. Dasselbe passiert wenn ich statt zu
> dividieren schieben um 11 benutze.

Warum ist das zu ungenau ?
Was sind das überhaupt für nen Haufen Werte?
Sind das Konstanten, kannst Du doch beim Compilieren den Korrekturfaktor 
2048/1800 einfach mit reinrechnen lassen.
Die Division ist jedenfalls das mit Abstand teuerste.
Und wenns ein ATmega ist, ist die Multipikation auch nicht so schlimm.

Wenn "allticks" bei jedem Aufruf konstant hoch- oder runterzählt, dann 
kann man die Rechnung auf eine einzige Addition verkürzen.
Die Tabelle enthält dann nicht mehr Faktoren, sondern die Schrittweite.
Das ist dann am schnellsten.

> Vor allem die IFs stören mich.

Die stören vielleicht optisch, von der Rechenzeit her sind es Pinats.

Was mich daran stört, ist das 10-fach Copy&Paste-Monster.
Es wird doch fast immer das gleiche gemacht, als ab damit ans Ende und 
nicht 10-mal kopieren.


Peter

Autor: Manax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen dank für eure schnelle Hilfe.
Der Hinweis mit dem case hat mich gerettet wusste gar nicht,dass das so 
funktioniert. (Spart mir schonmal 7µs ) macht die Sache übersichtlicher 
und vor allem erweiterbar.

Assembler kann ich leider nicht programmieren.
Ich würde die Division gerne rausziehen allerdings ist 
vorzuendung+zzp[idx] ein so kleiner Wert, dass die Rechnung viel zu 
ungenau wird.Allticks ist eine Variable.


Zur grundsätzlichen Funktion des Programms:

Dieser Programmteil soll die Zündverzögerung einer Zündung mit 
Verstellkurve errechnen. Der Wert in µs ist gesucht mit einem globalen 
Wert (in 0.2 Grad Schritten )und einem speziellen auf die Drehzahl 
abgestimmten Wert (in 0.2 Grad Schritten).


mfg Manax

Autor: Manax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
p.s. Ich bin fast verzweifelt bis ich den Fehler in der case gefunden 
habe.
Ein arraywert wird übersprungen zzp[1].

mfg

Autor: micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Man kann es erstmal übersichtlicher schreiben:
> void choosetable( void )
> {
>   uint8_t idx;
>   if( startup==1 )
>     allticks=15000;>
>   switch( allticks ){
>     case 11905 ... 65535: idx = 0; startup = 1; break;
>     case 7057 ... 11904: idx = 2; break;
>     case 5034 ... 7056: idx = 3; break;
>     case 3906 ... 5033: idx = 4; break;
>     case 3191 ... 3905: idx = 5; break;
>     case 2698 ... 3190: idx = 6; break;
>     case 2336 ... 2697: idx = 7; break;
>     case 2060 ... 2335: idx = 8; break;
>     case 1843 ... 2059: idx = 9; break;
>     case 1667 ... 1842: idx = 10; break;
>     default: return;
> }

Könnte mir jemand diese GCC Erweiterung erklären, da ich nur Standard 
c(++) behersche.
Prüft der Switch ob sich Werte dazwischen befinden? z.B. zwischen 1667 
... 1842 und wenn ja, wird idx zu 10 gesetzt?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Könnte mir jemand diese GCC Erweiterung erklären, da ich nur Standard
> c(++) behersche.

Das GCC-Handbuch kann das.

> Prüft der Switch ob sich Werte dazwischen befinden?

Nicht dazwischen, aber ob sie sich in dem angegebenen Bereich befinden, 
also inklusive den angegebenen Grenzwerten.

> z.B. zwischen 1667 ... 1842 und wenn ja, wird idx zu 10 gesetzt?

Ja.

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.