Domanda

Come si può misurare la quantità di tempo di una funzione da eseguire?

Questo è un relativamente breve, la funzione e il tempo di esecuzione sarebbe probabilmente essere in millisecondi gamma.

Questa particolare domanda si riferisce a un sistema embedded, programmato in C o C++.

È stato utile?

Soluzione

Il modo migliore per farlo su un sistema embedded è quello di impostare un hardware esterno pin quando si entra in funzione e chiaro che quando si lascia la funzione.Questo viene fatto preferibilmente con un po ' di istruzioni di montaggio in modo non inclinare i risultati di troppo.

Edit:Uno dei vantaggi è che si può fare nella vostra applicazione e non ha bisogno di alcun codice di test.Esterno debug pin come sono (dovrebbe essere!) pratica standard per ogni sistema embedded.

Altri suggerimenti

Ci sono tre possibili soluzioni:

Soluzione Hardware:

Utilizzare un pin di uscita del processore e il gancio di un oscilloscopio o logic analyzer per il pin.Inizializza il pin di basso stato, prima di chiamare la funzione che si vuole misurare, affermare il pin di un alto e poco dopo il ritorno dalla funzione, deassert il pin.


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

Bookworm soluzione:

Se la funzione è abbastanza piccolo, e si può gestire il codice disassemblato, è possibile decifrare l'architettura del processore databook e contare il ciclo prenderà il processore per l'esecuzione di tutte le istruzioni.Questo vi darà il numero di cicli richiesti.
Tempo = # cicli * Processore Frequenza di Clock / Clock ticks al istruzioni

Questo è più facile da fare per le piccole funzioni, o il codice scritto in assembler (per un microcontrollore PIC per esempio)

Contatore Timestamp soluzione:

Alcuni processori hanno un timestamp contatore che incrementi ad un ritmo rapido (ogni paio di clock del processore zecche).Basta leggere il timestamp prima e dopo la funzione.Questo vi darà il tempo trascorso, ma attenzione che si potrebbe avere a che fare con l'azzeramento del contatore.

Richiamare in un ciclo con una tonnellata di invocazioni, poi dividere per il numero di invocazioni per ottenere il tempo medio.

così:

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

se stai usando linux, è possibile il tempo di esecuzione di un programma di runtime digitando nella riga di comando:

time [funtion_name]

se si esegue solo la funzione main() (supponendo che il C++), il resto della app di tempo dovrebbe essere trascurabile.

Ripeto la funzione di chiamata un sacco di volte (in milioni) ma anche utilizzare il metodo riportato di seguito per sconto del loop:

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

Invece di chiamare la funzione() due volte nel primo ciclo e una volta nel secondo ciclo, si può solo chiamare una volta nel primo ciclo e non chiamare affatto (cioèvuoto loop) nel secondo, però il vuoto loop potrebbe essere ottimizzato dal compilatore, dando negativi risultati di sincronizzazione :)

start_time = timer
function()
exec_time = timer - start_time

Windows XP/NT Embedded o Windows CE/Mobile

È possibile utilizzare il QueryPerformanceCounter() per ottenere il valore di un contatore VELOCE prima e dopo la funzione.Poi si sottrae quelli a 64-bit di valori e di ottenere un delta "zecche".Utilizzando QueryPerformanceCounterFrequency() è possibile convertire il "delta zecche" ad una vera e propria unità di tempo.È possibile consultare la documentazione MSDN su quelle chiamate WIN32.

Altri sistemi embedded

Senza sistemi operativi o con solo la base di Sistemi operativi si dovrà:

  • programma di una delle CPU interna timer per eseguire e conte liberamente.
  • configurarlo per generare un interrupt quando il timer di overflow, e in questa routine di interrupt incremento di un "riporto" variabile (questo è così si può effettivamente misurare il tempo più lungo rispetto alla risoluzione del timer scelto).
  • prima della funzione si salva SIA il "portare" valore e il valore del registro della CPU tenendo l'esecuzione di zecche per il conteggio del timer è configurato.
  • stesso dopo che la funzione
  • sottrarre per ottenere un banco delta tick.
  • da lì è solo una questione di sapere per quanto tempo un segno di spunta significa che su CPU/Hardware dato il clock esterno e la de-moltiplicazione è configurato durante l'impostazione del timer.Si moltiplica il "tick lunghezza" dal "delta zecche" che hai appena ricevuto.

MOLTO IMPORTANTE Non dimenticate di disattivare prima e ripristino interrompe dopo il recupero di quei valori del timer (bot il carry e il valore del registro) altrimenti si rischia di risparmio di valori non corretti.

NOTE

  • Questo è molto veloce, perché è solo un paio di istruzioni di montaggio disabilitare gli interrupt, salva due valori interi e ri-abilitare gli interrupt.L'effettiva sottrazione e la conversione in tempo reale unità si verifica al di FUORI della zona di misurazione del tempo, che è DOPO la funzione.
  • Si può inserire il codice in una funzione di riutilizzare il codice in tutto, ma si può rallentare un po ' le cose a causa della funzione di chiamata e l'invio di tutti i registri nello stack, più i parametri, quindi li popping di nuovo.In un sistema embedded questo può essere significativo.Potrebbe essere migliore, quindi in C per l'utilizzo di MACRO, invece, o scrivere le vostre routine assembly salvataggio/ripristino di appositi registri.

Dipende dalla piattaforma embedded e che tipo di temporizzazione che si sta cercando.Per Linux embedded, ci sono diversi modi si può realizzare.Se si desidera misurare il lasso di tempo di CPU utilizzato dalla funzione, è possibile effettuare le seguenti operazioni:

#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;
}

Avrete bisogno di collegare questo con il realtime libreria, basta usare la seguente procedura per compilare il codice:

gcc -o test test.c -lrt

Si può anche leggere la pagina man su clock_gettime c'è qualche problema con l'esecuzione di questo codice scremato in polvere a base di sistema che potrebbero invalidare si prova.Si potrebbe usare qualcosa come sched_setaffinity() o la riga di comando cpuset per forza il codice su un solo core.

Se siete alla ricerca a misura di utente e l'ora di sistema, quindi è possibile utilizzare il times(NULL) che restituisce qualcosa di simile a un jiffies.O è possibile modificare il parametro per clock_gettime() da CLOCK_THREAD_CPUTIME_ID per CLOCK_MONOTONIC...ma attenzione, di avvolgente con CLOCK_MONOTONIC.

Per le altre piattaforme, siete sul proprio.

Drew

Ho sempre implementare un interrupt driven ticker di routine.Quindi, questo aggiorna un contatore che conta il numero di millisecondi trascorsi dall'avvio.Questo contatore è quindi possibile accedervi con un GetTickCount() funzione.

Esempio:

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

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

unsigned in GetTickCount(void)
{
    return tickCounter;
}

Nel tuo codice il codice come segue:

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

    do something ...

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

In OS X terminal (e, probabilmente, Unix, troppo), l'uso del "tempo":

time python function.py

Se il codice è .Net, utilizzare il cronometro classe (.net 2.0+) NON DateTime.Ora.DateTime.Ora non è aggiornato in maniera sufficientemente precisa e vi darà pazzo risultati

Se stai cercando inferiore al millisecondo risoluzione, provare uno di questi tempi metodi.Tutti di ottenere una risoluzione almeno di decine o centinaia di microsecondi:

Se si tratta di Linux embedded, guardare a Linux timer:

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

Embedded Java, guarda nanoTime(), anche se non sono sicuro che questo è in embedded edition:

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

Se si desidera ottenere i contatori hardware, provare PAPI:

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

Altrimenti si può sempre andare per assembler.Si potrebbe guardare il PAPI di origine per la tua architettura, se hai bisogno di aiuto con questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top