Calcolare tempo esecuzione codice



  • Calcolare tempo esecuzione codice...
    di cromagno data: 08/09/2015 22:23:33

    Buonasera a tutti,
    ieri, in altro forum si chiedeva se esistesse un modo per calcolare la velocità di esecuzione di una formula/codice rispetto ad un altra.
    Mi è venuto in mente un semplice codice che avevo già utilizzato (riportato sotto) e che per quell'occasione aveva funzionato bene.
    Nel proporre però l'esempio, quindi come riportato nel codice, il risultato ottenuto è sempre pari a zero.
    In effetti non c'è nulla da elaborare, ma possibile che sia istantaneo???
    Oppure c'è un limite... in tempo, sotto al quale per la funzione Timer è praticamente la stessa cifra (secondi)???
    Ho provato diversi "escamotage" ma il risultato è stato sempre quello, quindi la domanda che ho fatto mi sembra essere l'unica alternativa....

    Sbaglio qualcosa?

    Grazie in anticipo a chi risponderà
     
    Sub tempo()
    Dim start As Double, fine As Double, tempo As Double
    start = Timer
    
    
    'da mettere il proprio codice (o funzione tramite "Evaluate")
    
    
    fine = Timer
    tempo = fine - start
    MsgBox "L'esecuzione è durata " & tempo & " sec."
    End Sub



  • di scossa data: 08/09/2015 23:17:24

    cit.: "... se esistesse un modo per calcolare la velocità di esecuzione di una formula/codice rispetto ad un altra ..."

    Ma vorresti valutarlo sul calcolo di una sola formula?
    per esempio Evaluate ("SUM(A1:A10)")
    sul mio pc impiegherebbe meno di un millesimo di secondo: non puoi misurarlo con Timer

    Devi fare un ciclo: con il codice sotto, sul mio pc 0,1875 secondi
    Oppure usare le funzioni della libreria del kernel, ma comunque dovresti comunque fare più letture per minimizzare i tempi "spuri", per cui il codice sotto è sufficientemente preciso (dividi per il numero di iterazioni e avrai il tempo medio della singola operazione)


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.(George Bernard Shaw)

     
    Public Sub Timer_Test2()
      Dim nStart As Single
      Dim nStop As Single
      Dim j As Long
      
      nStart = Timer
      For j = 1 To 1000
        Evaluate ("SUM(A1:A10)")
      Next
      nStop = Timer - nStart
      Range("B1").Value = nStop
      
    End Sub
    



  • di cromagno data: 08/09/2015 23:55:45

    Esattamente scossa...
    la mia domanda era proprio come visualizzare quel "milli/microsecondo".
    Anche se credo che tu mi abbia già risposto dicendo che:
    "non puoi misurarlo con Timer"

    [EDIT]
    cmq si, col ciclo For puoi fare una media che risulterebbe più vicina al tempo reale dell'esecuzione della singola formula (certo, in base al ciclo).

    Grazie scossa



  • di scossa data: 09/09/2015 09:18:24

    cit.: "la mia domanda era proprio come visualizzare quel "milli/microsecondo"."

    Come dicevo devi usare le funzioni della libreria del kernel.
    Qui sotto trovi la funzione MicroTimer (tovata in rete ai tmepi che fu ...)

    Inserisci tutto in modulo standard.



    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.(George Bernard Shaw)

     
    '-------------- copy & paste in a standard module ---------------
    '
    'MicroTimer function
    'Found on the net
    '
    
    Private Declare Function getFrequency _
                Lib "kernel32" _
                Alias "QueryPerformanceFrequency" ( _
                cyFrequency As Currency) _
                As Long
    
    
    Private Declare Function getTickCount _
                Lib "kernel32" _
                Alias "QueryPerformanceCounter" _
                (cyTickCount As Currency) _
                As Long
    
    
    Public Function MicroTimer() As Double
        Dim cyTicks1 As Currency
        Static cyFrequency As Currency
        MicroTimer = 0
        If cyFrequency = 0 Then getFrequency cyFrequency
        getTickCount cyTicks1
        If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
    End Function
    
    '------------------- end copy ----------------
    
    
    
    'example to test function MicroTimer
    
    Public Sub Timer_Test()
      Dim dTime As Double
      Dim nTime As Double
      Dim j As Long
      
      dTime = MicroTimer
      For j = 1 To 1
        Evaluate ("SUM(A1:A10)")
      Next
      nTime = MicroTimer - dTime
      Range("B1").Value = nTime
      Range("C1").Value = nTime / 86400
      Range("C1").NumberFormat = "[m]:ss.000"
      
    End Sub



  • di ninai data: 09/09/2015 09:36:33

    ciao

    dicendola terra terra, uno come me, per sapere fra due o più formule quale è la più veloce, cosa deve farne del codice???

    es. copio il codice in un modulo di un file vuoto, poi inserisco le varie formule ed avvio la macro???

    oppure.......



  • di scossa data: 09/09/2015 09:53:38

    cit. ninai: "es. copio il codice in un modulo di un file vuoto, poi inserisco le varie formule ed avvio la macro???"

    in un modulo standard (F11 -> menu Inserisci -> modulo) incolli tutto il codice sotto riportato.
    Poi nella cella E1 scrivi la tua formula da valutare, p.e.: SOMMA(A1:A100) e poi lanci la macro.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.(George Bernard Shaw)

     
    Public Sub Timer_Test()
      Dim dTime As Double
      Dim nTime As Double
      Dim j As Long
      Dim n As Long
      
      n = 1 'cambiare con valore a piacere per effettuare più iterazioni
      dTime = MicroTimer
      For j = 1 To n 
        [E1] 'cella che contiene la formula da valutare
      Next
      nTime = MicroTimer - dTime
      Range("B1").Value = nTime
      Range("C1").Value = nTime / 86400
      Range("C1").NumberFormat = "[m]:ss.000"
      
    End Sub
      



  • di scossa data: 09/09/2015 09:54:44

    Edit: riposto tutto il codice da incollare.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.
    (George Bernard Shaw)

     
    '-------------- copy & paste in a standard module ---------------
    '
    'MicroTimer function
    'Found on the net
    '
    
    Private Declare Function getFrequency _
                Lib "kernel32" _
                Alias "QueryPerformanceFrequency" ( _
                cyFrequency As Currency) _
                As Long
    
    
    Private Declare Function getTickCount _
                Lib "kernel32" _
                Alias "QueryPerformanceCounter" _
                (cyTickCount As Currency) _
                As Long
    
    
    Public Function MicroTimer() As Double
        Dim cyTicks1 As Currency
        Static cyFrequency As Currency
        MicroTimer = 0
        If cyFrequency = 0 Then getFrequency cyFrequency
        getTickCount cyTicks1
        If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
    End Function
    
    '------------------- end copy ----------------
    
    
    
    'example to test function MicroTimer
    
    Public Sub Timer_Test()
      Dim dTime As Double
      Dim nTime As Double
      Dim j As Long
      
      dTime = MicroTimer
      For j = 1 To 1
        [E1]
      Next
      nTime = MicroTimer - dTime
      Range("B1").Value = nTime
      Range("C1").Value = nTime / 86400
      Range("C1").NumberFormat = "[m]:ss.000"
      
    End Sub
      
    
    



  • di ninai data: 09/09/2015 10:47:16

    grazie scossa
    ma di da errore di compilazione:
    "il codice del progetto deve essere aggiornato per l'utilizzo in sistemi a 64 bit. Esaminare e aggiornare le informazioni declare, quindi contrassegnarle con l'attributo PtrSafe"

    e poi il nome della macro mi sembra anomalo
    'cronometra tempi di esecuzione formule.xlsm'!Modulo1.Timer_Test

    sbaglierò qualcosa di sicuro


    mi chiedevo inoltre
    inserendo formule che fanno ,ovviamente, riferimento a celle , dati, e/o fogli presenti in altri file, la cosa non perturba la misurazione???



  • di scossa data: 09/09/2015 11:42:48

    cit.: "ma di da errore di compilazione"

    Sostituisci il tutto con quanto sotto.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.
    (George Bernard Shaw)

     
    '-------------- copy & paste in a standard module ---------------
    '
    'MicroTimer function
    'Found on the net
    '
    #If VBA7 Then
    
      Private Declare PtrSafe Function getFrequency _
                  Lib "kernel32" _
                  Alias "QueryPerformanceFrequency" ( _
                  cyFrequency As Currency) _
                  As Long
      
      
      Private Declare PtrSafe Function getTickCount _
                  Lib "kernel32" _
                  Alias "QueryPerformanceCounter" _
                  (cyTickCount As Currency) _
                  As Long
    #Else
      Private Declare Function getFrequency _
                  Lib "kernel32" _
                  Alias "QueryPerformanceFrequency" ( _
                  cyFrequency As Currency) _
                  As Long
      
      
      Private Declare Function getTickCount _
                  Lib "kernel32" _
                  Alias "QueryPerformanceCounter" _
                  (cyTickCount As Currency) _
                  As Long
    #End If
    
    
    
    Public Function MicroTimer() As Double
        Dim cyTicks1 As Currency
        Static cyFrequency As Currency
        MicroTimer = 0
        If cyFrequency = 0 Then getFrequency cyFrequency
        getTickCount cyTicks1
        If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
    End Function
    
    '------------------- end copy ----------------
    
    
    
    'example to test function MicroTimer
    
    Public Sub Timer_Test()
      Dim dTime As Double
      Dim nTime As Double
      Dim j As Long
      Dim n As Long
      
      n = 100 'cambiare con valore a piacere per effettuare più iterazioni
      dTime = MicroTimer
      For j = 1 To n
        [E1] 'cella che contiene la formula da valutare
      Next
      nTime = MicroTimer - dTime
      Range("B1").Value = nTime
      Range("C1").Value = nTime / 86400
      Range("C1").NumberFormat = "[m]:ss.000"
      
    End Sub



  • di scossa data: 09/09/2015 11:53:59

    cit.: "inserendo formule che fanno ,ovviamente, riferimento a celle , dati, e/o fogli presenti in altri file, la cosa non perturba la misurazione???"

    N.B.: non parte nessun cronometro o processo che interferisca con la valutazione della formula.

    Tu inserisci in una cella la formula;
    lanci la macro;
    viene memorizzato in una variabile il tempo (al microsecondo) di inizio della valutazione ;
    la formula nella cella viene valutata (per quanto complessa sia);
    viene memorizzato in una variabile il tempo (al microsecondo) di termine;
    viene mostrata la differenza fra le due variabili.



    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.(George Bernard Shaw)



  • di ninai data: 09/09/2015 12:30:30

    ok
    adesso la macro gira

    Perciò, se ho capito bene, i tempi di elaborazione non cambiano se i dati esistono o meno e se sono su quel foglio o su un altro.



  • di scossa data: 09/09/2015 12:59:59

    cit. ninai: "i tempi di elaborazione non cambiano se i dati esistono o meno e se sono su quel foglio o su un altro. "

    Non capisco cosa intendi.
    Se l'ambaradan ti serve per confrontare la velocità di due formule (p.e. Indice+Confronta vs Cerca.Vert) non è che in una metti tutti i riferimenti a celle sullo stesso foglio e nell'altra i dati li hai su file diversi, perché il confronto non avrebbe senso.

    In tutto questo il "timer" non ha nessun peso.


    scossa's web site
    Se tu hai una mela, ed io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee.(George Bernard Shaw)



  • di cromagno data: 09/09/2015 18:49:01

    Avevo letto qualcosa riguardo "micro timer" ma non ero riuscito a trovare nulla che mi facesse capire bene.
    Grazie ancora scossa



  • di ninai data: 09/09/2015 19:55:01

    scossa

    tutto ok, non ci fare caso, neanche io capisco cosa intendevo



  • di perché (utente non iscritto) data: 09/09/2015 20:25:22

    Per ulteriori chiarimenti, qui

    h t t p ://www.vbaexpress.com/kb/getarticle.php?kb_id=1068

    il codice originale ...



  • di alfrimpa data: 09/09/2015 20:31:36

    @ perché

    Ho visitato il link che hai postato ma riferimenti a questa discussione non ne ho trovati neanche l'ombra.

    Alfredo





  • di perché (utente non iscritto) data: 09/09/2015 20:39:23

    Che vuoi dire?

    Io ho solo scritto che quello è il codice "originale" del 2006 della funzione suggerita (MicroTimer) e che c'è un (altro) esempio di utilizzo da studiare. Tutto qui.