Forum: Mikrocontroller und Digitale Elektronik Wie lange dauert ein Prozessschritt?


von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

bin Anfänger.
Ich möchte innerhlab eines Programmes (s.ICP_UART_162_01.c) vom Programm 
durchgeführte Berechnungen auf ihren Zeitverbrauch hin messen.

dazu schalte ich vor der Rechnung PINA4 auf 0 und nach der Messung 
wieder auf 1. Das dabei entstehende negative Signal messe ich mit dem 
Oszi.

Habe das Bild angehängt.

Nun die Frage:

Es ist egal, welche Berechnung ich messe, ob

Erg=Erg*100 / 36 oder die Nachfolgende, oder aber alle drei( incl
signal = Faktor*1.000.000 / Erg,

Es kommt immer ein Wert um die 13,84 µs raus.  Habe ich hier einen 
grundsätzlichen Denkfehler?

Würde mich über einen Tipp freuen

Thomas

von X- R. (x-rocka)


Lesenswert?

edit.

Kuck dir mal das Listing / Assembler an, vor allem wenn du nur eine oder 
alle 3 Berechnungen verwendest. Sollte eigentlich bei 3 Berechnungen 
länger dauern.

von Jobst M. (jobstens-de)


Lesenswert?

Thomas schrieb:
> Es kommt immer ein Wert um die 13,84 µs raus.

Deine Grafik zeigt aber etwas anderes ...


Gruß

Jobst

von ulrich (Gast)


Lesenswert?

Die C Compiler können da einiges Optimieren. Es ist gut möglich das sich 
durch die Umstellung der Faktoren am erzeugten Code nichts ändert. 
Einiger der Faktoren werden auch schon zur Laufzeit zusammengefasst - 
soweit es halt geht.  Ob man 10000 oder 10*10*100 schreibt ist z.B. 
egal.

von Thomas (Gast)


Lesenswert?

....weil ich aus der *.lss Datei nicht schlau werde, hatte ich versucht 
das Problem in der oben beschriebenen Art zu löen. In der assemblerdatei 
kann ich die einzelnen Rechenschritte nicht differenzieren, da ich kein 
assembler kann.

In der assemblerdatei werden auch nicht alle Kommentierungen angezeigt, 
an denen ich mich hätte orientieren können.

Gruß

Thomas

von Thomas (Gast)


Lesenswert?

@ Jobst

sorry, ich habe das erste Mal mein neues Oszi in Betreib genommen. Habe 
vorher noch nie sowas genutzt. kann sein, dass ich damit vielleicht was 
ganz anderes gemessen hatte?

Gruß
Thomas

von Andreas B. (Gast)


Lesenswert?

Wenn Optimierungen eingeschaltet sind, wird der Compiler die 
Berechnungen nicht zwangsläufig zwischen den Zuweisungen an PORTA 
durchführen. Die Initialisierung von Erg greift auf volatile Variablen 
zu und wird deshalb zwangsläufig vor dem ersten PORTA Zugriff 
abgearbeitet. Die anderen Berechnungen aber kann der Compiler beliebig 
umformen und auch hinter den zweiten PORTA verschieben, es zählt nur das 
Ergebnis signal, das itoa() übergeben wird.

von Jobst M. (jobstens-de)


Lesenswert?

Thomas schrieb:
> @ Jobst
>
> sorry, ich habe das erste Mal mein neues Oszi in Betreib genommen. Habe
> vorher noch nie sowas genutzt. kann sein, dass ich damit vielleicht was
> ganz anderes gemessen hatte?
>
> Gruß
> Thomas

Naja, etwa 180us ...


Gruß

Jobst

von X- R. (x-rocka)


Lesenswert?

Andreas B. schrieb:
> Wenn Optimierungen eingeschaltet sind, wird der Compiler die
> Berechnungen nicht zwangsläufig zwischen den Zuweisungen an PORTA
> durchführen. Die Initialisierung von Erg greift auf volatile Variablen
> zu und wird deshalb zwangsläufig vor dem ersten PORTA Zugriff
> abgearbeitet. Die anderen Berechnungen aber kann der Compiler beliebig
> umformen und auch hinter den zweiten PORTA verschieben, es zählt nur das
> Ergebnis signal, das itoa() übergeben wird.

Echt, so wat fieses tun Compiler?!

von Rolf M. (rmagnus)


Lesenswert?

Ja. Ist nach ISO-C auch völlig ok. Das nennt sich "as-if rule" und 
besagt, daß das Programm nicht exakt das tun muß, was im Code steht, 
sondern daß es reicht, wenn das "observable behavior" gleich ist, und 
das ist definiert über I/O und den Zugriff auf volatile-Variablen. Alles 
andere darf beliebig verändert, umsortiert, zusammengefaßt oder 
wegoptimiert werden.

von Thomas (Gast)


Lesenswert?

An alle:

Vielen dank für Eure Hilfe!
Insbesondere die erklärungen von Andreas B in Hinblick auf das 
Compilerverhalten waren sehr erhellend!

Gruß

Thoms

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Ja. Ist nach ISO-C auch völlig ok. Das nennt sich "as-if rule" und
> besagt, daß das Programm nicht exakt das tun muß, was im Code steht,
> sondern daß es reicht, wenn das "observable behavior" gleich ist
Aber das beobachtbare Verhalten ist m.E. anders, wenn der Compiler
aus dem hier:
1
    PORTA &= ~(1<<PA4); // neg. Peak beginnt
2
   
3
    Erg = Erg*100 / 36; 
4
    Faktor = Erg*65 / 10000;
5
    signal = Faktor*1000000 / Erg; 
6
7
    PORTA |= (1<<PA4); // neg Peak endet
das hier macht:
1
    PORTA &= ~(1<<PA4); // neg. Peak beginnt
2
    PORTA |= (1<<PA4);  // neg Peak endet
3
   
4
    Erg = Erg*100 / 36; 
5
    Faktor = Erg*65 / 10000;
6
    signal = Faktor*1000000 / Erg;
Das dürfte er ja.

Und wenn es tatsächlich so ist, wie kann ich den Compiler sanft dazu 
zwingen, mir die Beobachtung der Rechenzeit zu ermöglichen? Ist da mit 
Klammern/Blöcken was zu machen?
1
    PORTA &= ~(1<<PA4); // neg. Peak beginnt
2
    {   
3
    Erg = Erg*100 / 36; 
4
    Faktor = Erg*65 / 10000;
5
    signal = Faktor*1000000 / Erg; 
6
    }
7
    PORTA |= (1<<PA4); // neg Peak endet

Und was ist bei sowas:
1
void calc() 
2
{
3
    Erg = Erg*100 / 36; 
4
    Faktor = Erg*65 / 10000;
5
    signal = Faktor*1000000 / Erg; 
6
}
7
:
8
:
9
    PORTA &= ~(1<<PA4); // neg. Peak beginnt
10
    calc();
11
    PORTA |= (1<<PA4); // neg Peak endet
Darf der Compiler das auch umstellen:
1
void calc() 
2
{
3
    Erg = Erg*100 / 36; 
4
    Faktor = Erg*65 / 10000;
5
    signal = Faktor*1000000 / Erg; 
6
}
7
:
8
:
9
    PORTA &= ~(1<<PA4); // neg. Peak beginnt
10
    PORTA |= (1<<PA4);  // neg Peak endet
11
    calc();

Oder, um die Frage umzustellen:
(Wie) kann ich denn mit den hier aufgeführten Mitteln (Oszi + Portpin) 
die benötigte Zeit für eine Berechnung ermitteln?

Es hilft ja nichts, alle beteiligten Variablen auf volatile zu setzen, 
das wäre dann ja nicht mehr der Code, den ich eigentlich vermessen 
will...

von Andreas B. (Gast)


Lesenswert?

Der Compiler darf auch den Funktionsaufruf umstellen und auch inline 
expandieren. Um es wirklich so mit Port-Pin zu machen, sollte im GCC 
wohl das funktionieren:
1
int result = 0;     // wird als Dummy verwendet
2
3
PORTA &= ~(1<<PA4); // neg. Peak beginnt
4
asm volatile ("" : "X"(result));
5
result = calc();
6
asm volatile ("" : "X"(result));
7
PORTA |= (1<<PA4);  // neg Peak endet

Damit wird ein Assembler-Befehl eingefügt (tatsächlich nur ein leerer 
String) und dem Compiler gesagt, dass er den nicht wegoptimieren darf. 
Dazu dann wird result darin referenziert, so dass auch da die 
Reihenfolge nicht geändert werden kann.


Eine bessere Möglichkeit auch ohne Oszi dürfte sein, alles in eine 
Funktion zu packen (die das Ergebnis auch zurück gibt, damit halt nicht 
der ganze Inhalt der Funktion wegoptimiert wird) und die in einer 
anderen Datei (um dem Compiler Kenntnisse um Inhalt der Funktion zu 
verweigern) in einer Schleife 10000 mal oder so aufzurufen.

Die Zeit der ganzen Schleife geteilt durch die Durchläufe gibt dann die 
Laufzeit der Funktion (+ Aufruf + Schleife). Man kann das ganze noch mal 
mit einer leeren Funktion machen, dann sollte man die Zeit für Aufruf 
und Schleife haben und kann die vom ersten Wert abziehen.

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.