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
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.
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.
....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
@ 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
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.
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
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?!
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.
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
voidcalc()
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
voidcalc()
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...
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.
Eine eigene Frage?
Dieser Thread ist über 15 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.