Frage

Wie kann man die Menge an Zeit misst eine Funktion auszuführen nehmen?

Dies ist eine relativ kurze Funktion und die Ausführungszeit wahrscheinlich im Millisekunden-Bereich sein würden.

Diese besondere Frage bezieht sich auf ein eingebettetes System, programmiert in C oder C ++.

War es hilfreich?

Lösung

Die beste Art und Weise, dass auf einem Embedded-System zu tun, ist einen externen Hardware-Stift zu setzen, wenn Sie die Funktion und deaktivieren Sie es eingeben, wenn Sie die Funktion verlassen. Dies wird vorzugsweise mit einer kleinen Montageanleitung durchgeführt, so dass Sie Ihre Ergebnisse nicht zu viel schief.

Edit: Einer der Vorteile ist, dass Sie es in Ihrer aktuellen Anwendung tun können und Sie keinen speziellen Testcode benötigen. Externer Debug-Pins wie das ist (soll!) Gängige Praxis für jedes Embedded System.

Andere Tipps

Es gibt drei mögliche Lösungen:

Hardware-Lösung :

einen Oszilloskop oder Logikanalysator zum Stift

einen freien Ausgangsstift auf dem Prozessor und Haken. Initialisieren Sie den Stift auf einen niedrigen Zustand, kurz vor dem Aufruf der Funktion, die Sie messen wollen, behaupten den Stift auf einen hohen Zustand und nur, nachdem sie von der Funktion zurückkehrt, deassert dem Stift.


    *io_pin = 1;
    myfunc();
    *io_pin = 0;

Bookworm Lösung :

Wenn die Funktion ziemlich klein ist, und Sie können die demontierten Code verwalten, können Sie knacken die Prozessorarchitektur Datenbuch öffnen und die Zyklen zählen es wird den Prozessor nehmen alle Anweisungen auszuführen. Dies gibt Ihnen die Anzahl der Zyklen erforderlich.
Time = # Zyklen * Prozessor Taktrate / Uhr tickt pro Anweisungen

Das ist einfacher für kleinere Funktionen zu tun, oder Code in Assembler geschrieben (für einen PIC-Mikrocontroller zum Beispiel)

Timestamp Zähler Lösung :

Einige Prozessoren haben einen Zeitstempel-Zähler, der (alle paar Prozessortakt tickt) mit einer schnellen Rate erhöht. Lesen Sie einfach den Zeitstempel vor und nach der Funktion. Dies wird Ihnen die verstrichene Zeit geben, aber Vorsicht, dass Sie mit der Gegenüberschlags zu tun haben könnten.

Rufen Sie es mit einer Tonne von Anrufungen in einer Schleife, dann teilen Sie durch die Anzahl der Anrufungen die durchschnittliche Zeit zu erhalten.

so:

// begin timing
for (int i = 0; i < 10000; i++) {
    invokeFunction();
}
// end time
// divide by 10000 to get actual time.

Wenn Sie Linux verwenden, können Sie, indem Sie in der Befehlszeile eines Programms Laufzeit Zeit:

time [funtion_name]

, wenn Sie die Funktion im Hauptlauf () (unter der Annahme, C ++), der Rest der Zeit der App sollte vernachlässigbar sein.

Ich wiederhole die Funktion eine Menge Zeit (in Millionen) nennen, aber auch die folgende Methode verwenden, um die Schleife Overhead zu diskontieren:

start = getTicks();

repeat n times {
    myFunction();
    myFunction();
}

lap = getTicks();

repeat n times {
    myFunction();
}

finish = getTicks();

// overhead + function + function
elapsed1 = lap - start;

// overhead + function
elapsed2 = finish - lap;

// overhead + function + function - overhead - function = function
ntimes = elapsed1 - elapsed2;

once = ntimes / n; // Average time it took for one function call, sans loop overhead

Stattdessen function () zweimal in der ersten Schleife und einmal in der zweiten Schleife zu nennen, könnte man es nur einmal in der ersten Schleife nennen und es nicht überhaupt nennen (dh leere Schleife) in den zweiten, aber die leere Schleife durch den Compiler könnte optimiert heraus, Sie negatives Timing Ergebnisse geben:)

start_time = timer
function()
exec_time = timer - start_time

Windows XP / NT Embedded oder Windows CE / Mobile-

Sie eine Verwendung der Queryperformancecounter () den Wert eines sehr schnellen Zähler vor und nach Ihrer Funktion zu erhalten. Dann subtrahieren Sie diese 64-Bit-Werte und ein Delta bekommen „Ticks“. Mit QueryPerformanceCounterFrequency () können Sie die „Delta-Ticks“ auf eine tatsächliche Zeiteinheit zu konvertieren. Sie können über diese WIN32 Anrufe auf MSDN-Dokumentation.

Andere eingebettete Systeme

Ohne Betriebssysteme oder mit nur grundlegendem OSes müssen Sie:

  • Programm eine des internen CPU-Timer frei laufen und zu zählen.
  • konfiguriert, dass eine Unterbrechung, wenn der Zeitgeber überläuft, und in diesem Interrupt-Routine Schritt a „tragen“ Variable zu erzeugen (dies ist so können Sie tatsächlich Zeit, die länger ist als die Auflösung des Timers gewählt messen).
  • , bevor Sie Ihre Funktion, die Sie sowohl die „carry“ Wert und der Wert der CPU-Register speichern den Lauf Ticks für das Zählen Timer halten Sie konfigurieren.
  • same nach Ihrer Funktion
  • subtrahieren sie einen Delta-Zähler Zecke zu erhalten.
  • von dort aus ist es nur eine Sache zu wissen, wie lange ein Häkchen bedeutet auf Ihrer CPU / Hardware angesichts der externen Takt und die de-Multiplikation Sie konfiguriert, während die Timer-Einrichtung. Sie multiplizieren, dass „tick Länge“ von der „Delta-Zecken“ Sie ist jetzt noch.

SEHR WICHTIG Vergessen Sie nicht, bevor zu deaktivieren und wiederherstellen Interrupts nach dieser Zeitwerte erhalten (bot den Übertrag und dem Registerwert) sonst riskieren Sie falsche Werte zu speichern.

NOTES:

  • Das ist sehr schnell, weil es nur wenige Montageanleitung ist Interrupts zu deaktivieren, speichert zwei Integer-Werte und erneut aktivieren Interrupts. Die tatsächliche Substraktion und die Umstellung auf Echtzeiteinheiten erfolgt außerhalb der Zone der Zeitmessung, die nach Ihrer Funktion ist.
  • Sie können wünschen, dass Code in eine Funktion zu setzen, dass Code alle um wieder zu verwenden, aber es kann ein bisschen langsam Dinge wegen der Funktionsaufruf und das Drücken aller Register auf den Stapel, und die Parameter, dann sie wieder knallen . In einem eingebetteten System kann dies von Bedeutung sein. Es kann in C besser als sein MACROS zu verwenden, anstatt oder Ihre eigene Montage Routine Spar Schreib- / Wiederherstellung nur relevante Register.

Abhängig von Ihrer Embedded-Plattform und welche Art von Timing für Sie suchen. Für Embedded Linux, gibt es mehrere Möglichkeiten, wie Sie erreichen können. Wenn Sie die amout der CPU-Zeit, indem Sie Ihre Funktion messen möchten, können Sie wie folgt vor:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#define SEC_TO_NSEC(s) ((s) * 1000 * 1000 * 1000)

int work_function(int c) {
    // do some work here
    int i, j;
    int foo = 0;
    for (i = 0; i < 1000; i++) {
        for (j = 0; j < 1000; j++) {
            for ^= i + j;
        }
    }
}

int main(int argc, char *argv[]) {
    struct timespec pre;
    struct timespec post;
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &pre);
    work_function(0);
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &post);

    printf("time %d\n",
        (SEC_TO_NSEC(post.tv_sec) + post.tv_nsec) -
        (SEC_TO_NSEC(pre.tv_sec) + pre.tv_nsec));
    return 0;
}

Sie müssen dies mit der Echtzeit-Bibliothek verknüpfen, verwenden Sie einfach den folgenden Code zu kompilieren:

gcc -o test test.c -lrt

Sie können auch die Manpage auf clock_gettime lesen gibt es einige Probleme, diesen Code auf SMP-basiertes System mit ausgeführt wird, die Sie mit dem Testen ungültig machen könnte. Man könnte so etwas wie sched_setaffinity() oder die Befehlszeile cpuset zu zwingen, den Code auf nur einen Kern verwenden.

Wenn Sie schauen, Benutzer- und Systemzeit zu messen, dann könnte man die times(NULL) benutzen, die so etwas wie ein jiffies zurückgibt. Oder Sie können die Parameter für clock_gettime() von CLOCK_THREAD_CPUTIME_ID ändern CLOCK_MONOTONIC ... aber vorsichtig sein, Wrap-around mit CLOCK_MONOTONIC.

Für andere Plattformen, Sie sind auf eigene Faust.

Drew

Ich habe immer einen Interrupt getrieben Ticker Routine implementieren. Dies aktualisiert dann einen Zähler, der die Anzahl der Millisekunden seit dem Start bis zählt. Dieser Zähler wird dann mit einer GetTickCount () Funktion aufgerufen.

Beispiel:

#define TICK_INTERVAL 1    // milliseconds between ticker interrupts
static unsigned long tickCounter;

interrupt ticker (void)  
{
    tickCounter += TICK_INTERVAL;
    ...
}

unsigned in GetTickCount(void)
{
    return tickCounter;
}

In Ihrem Code würden Sie den Code Zeit wie folgt:

int function(void)
{
    unsigned long time = GetTickCount();

    do something ...

    printf("Time is %ld", GetTickCount() - ticks);
}

In OS X-Terminal (und wahrscheinlich auch Unix auch), verwenden Sie "Zeit":

time python function.py

Wenn der Code .Net ist, verwenden Sie die Stoppuhr-Klasse (.net 2.0+) NICHT DateTime.Now. DateTime.Now nicht genau genug aktualisiert und werden Sie verrückt Ergebnisse geben

Wenn Sie sich für Sub-Millisekunden-Auflösung suchen, versuchen Sie eine dieser Timing-Methoden. Sie werden alle erhalten Sie die Auflösung mindestens die Dutzende oder Hunderte von Mikrosekunden:

Wenn es Linux eingebettet ist, schauen Linux-Timer:

http://linux.die.net/man/3/clock_gettime

Embedded Java, Blick auf Nanotime (), obwohl ich nicht sicher bin, dies in der Embedded-Ausgabe lautet:

http: / /java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#nanoTime ()

Wenn Sie an den Hardware-Zähler erhalten möchten, versuchen PAPI:

http://icl.cs.utk.edu/papi/

Ansonsten können Sie immer auf Assembler gehen. Sie könnten für Ihre Architektur an der PAPI Quelle aussehen, wenn Sie etwas Hilfe brauchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top