velocidad trabajo reaccion para mejora futbol entrenamiento ejercicios como aumentar aumenta agilidad agarrar performance delphi optimization gettickcount

performance - para - trabajo de reaccion y velocidad



Calculando la velocidad de las rutinas? (8)

Lo pregunto porque actualmente estoy tratando de optimizar algunas funciones

Es natural pensar que la medición es la forma de descubrir qué optimizar, pero hay una mejor manera.

Si algo toma una fracción de tiempo suficientemente grande (F) para que valga la pena optimizarlo, entonces si simplemente lo pausa al azar, F es la probabilidad de que lo atrape en el acto. Haga eso varias veces, y verá exactamente por qué lo hace, hasta las líneas exactas de código.

Más sobre eso. Aquí hay un ejemplo.

Arréglalo y luego realiza una medición general para ver cuánto ahorraste, lo cual debería ser aproximadamente F. Enjuagar y repetir.

¿Cuál sería la mejor y más precisa forma de determinar cuánto tiempo tomó procesar una rutina, como un procedimiento de función?

Pregunto porque actualmente estoy tratando de optimizar algunas funciones en mi aplicación, cuando pruebo los cambios es difícil de determinar con solo mirar si hubo alguna mejora. Entonces, si pudiera devolver una hora exacta o casi exacta para procesar una rutina, entonces tendré una idea más clara de qué tan bien, si se han realizado cambios en el código.

Consideré usar GetTickCount, pero no estoy seguro de si esto sería casi exacto.

Sería útil contar con una función / procedimiento de cálculo para calcular el tiempo de una rutina y usarlo de la siguiente manera:

// < prepare for calcuation of code ... ExecuteSomeCode; // < code to test ... // < stop calcuating code and return time it took to process

Espero escuchar algunas sugerencias.

Gracias.

Craig.


Aquí hay algunos procedimientos que hice para controlar la duración de una función. Los metí en una unidad que llamé uTesting y luego simplemente uTesting la cláusula uses durante mi prueba.

Declaración

Procedure TST_StartTiming(Index : Integer = 1); //Starts the timer by storing now in Time //Index is the index of the timer to use. 100 are available Procedure TST_StopTiming(Index : Integer = 1;Display : Boolean = True; DisplaySM : Boolean = False); //Stops the timer and stores the difference between time and now into time //Displays the result if Display is true //Index is the index of the timer to use. 100 are available Procedure TST_ShowTime(Index : Integer = 1;Detail : Boolean = True; DisplaySM : Boolean = False); //In a ShowMessage displays time //Uses DateTimeToStr if Detail is false else it breaks it down (H,M,S,MS) //Index is the index of the timer to use. 100 are available

variables declaradas

var Time : array[1..100] of TDateTime;

Implementación

Procedure TST_StartTiming(Index : Integer = 1); begin Time[Index] := Now; end; Procedure TST_StopTiming(Index : Integer = 1;Display : Boolean = True; DisplaySM : Boolean = False); begin Time[Index] := Now - Time[Index]; if Display then TST_ShowTime; end; Procedure TST_ShowTime(Index : Integer = 1;Detail : Boolean = True; DisplaySM : Boolean = False); var H,M,S,MS : Word; begin if Detail then begin DecodeTime(Time[Index],H,M,S,MS); if DisplaySM then ShowMessage(''Hour = '' + FloatToStr(H) + #13#10 + ''Min = '' + FloatToStr(M) + #13#10 + ''Sec = '' + FloatToStr(S) + #13#10 + ''MS = '' + FloatToStr(MS) + #13#10) else OutputDebugString(PChar(''Hour = '' + FloatToStr(H) + #13#10 + ''Min = '' + FloatToStr(M) + #13#10 + ''Sec = '' + FloatToStr(S) + #13#10 + ''MS = '' + FloatToStr(MS) + #13#10)); end else ShowMessage(TimeToStr(Time[Index])); OutputDebugString(Pchar(TimeToStr(Time[Index]))); end;


Desde Delphi 6 en adelante puede usar el contador x86 Timestamp.
Esto cuenta ciclos de CPU, en un procesador de 1 Ghz, cada cuenta demora un nanosegundo.
No se puede obtener más exacto que eso.

function RDTSC: Int64; assembler; asm // RDTSC can be executed out of order, so the pipeline needs to be flushed // to prevent RDTSC from executing before your code is finished. // Flush the pipeline XOR eax, eax PUSH EBX CPUID POP EBX RDTSC //Get the CPU''s time stamp counter. end;

En x64, el siguiente código es más preciso, ya que no sufre el retraso de CPUID .

rdtscp // On x64 we can use the serializing version of RDTSC push rbx // Serialize the code after, to avoid OoO sneaking in push rax // subsequent instructions prior to executing RDTSCP. push rdx // See: http://www.intel.de/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf xor eax,eax cpuid pop rdx pop rax pop rbx shl rdx,32 or rax,rdx

Use el código anterior para obtener la marca de tiempo antes y después de ejecutar su código.
El método más preciso posible y fácil como circular.

Tenga en cuenta que debe ejecutar una prueba al menos 10 veces para obtener un buen resultado, en el primer paso la memoria caché estará fría y las lecturas aleatorias de disco duro y las interrupciones pueden afectar sus tiempos.
Debido a que esto es tan preciso, puede darte una idea equivocada si solo cronometras la primera carrera.

Por qué no deberías usar QueryPerformanceCounter ()
QueryPerformanceCounter() da la misma cantidad de tiempo si la CPU se ralentiza, compensa el colapso de la CPU. Mientras RDTSC le dará la misma cantidad de ciclos si su CPU se desacelera debido al sobrecalentamiento o lo que sea.
Entonces, si su CPU comienza a funcionar en caliente y necesita acelerarse, QueryPerformanceCounter() dirá que su rutina lleva más tiempo (lo cual es engañoso) y RDTSC dirá que lleva la misma cantidad de ciclos (lo cual es preciso) .
Esto es lo que quiere porque le interesa la cantidad de ciclos de CPU que utiliza su código, no la hora del reloj de pared.

De los últimos documentos de intel: http://software.intel.com/en-us/articles/measure-code-sections-using-the-enhanced-timer/?wapkw=%28rdtsc%29

Usando los relojes del procesador

Este temporizador es muy preciso. En un sistema con un procesador 3GHz, este temporizador puede medir eventos que duran menos de un nanosegundo. [...] Si la frecuencia cambia mientras el código objetivo se está ejecutando, la lectura final será redundante ya que las lecturas inicial y final no se tomaron usando la misma frecuencia de reloj. La cantidad de marcas de reloj que ocurrieron durante este tiempo será precisa , pero el tiempo transcurrido será desconocido.

Cuándo no usar RDTSC
RDTSC es útil para el tiempo básico. Si está sincronizando el código multiproceso en una sola máquina de CPU, RDTSC funcionará bien. Si tiene varias CPU, la cuenta de inicio puede provenir de una CPU y la cuenta de finalización de otra.
Por lo tanto, no use RDTSC para sincronizar el código multiproceso en una máquina con varias CPU. En una sola máquina de la CPU funciona bien, o código de un solo hilo en una máquina con varias CPU, también está bien.
Recuerde también que RDTSC cuenta los ciclos de CPU. Si hay algo que lleva tiempo pero no utiliza la CPU, como disk-IO o network que RDTSC no es una buena herramienta.

Pero la documentación dice que RDTSC no es precisa en las CPU modernas
RDTSC no es una herramienta para hacer un seguimiento del tiempo, es una herramienta para realizar un seguimiento de los ciclos de CPU.
Para eso, es la única herramienta que es precisa. Las rutinas que hacen un seguimiento del tiempo no son precisas en las CPU modernas porque el reloj de la CPU no es tan absoluto como solía ser.


No especificó su versión de Delphi, pero Delphi XE tiene un TStopWatch declarado en Diagnósticos de la unidad. Esto le permitirá medir el tiempo de ejecución con una precisión razonable.

uses Diagnostics; var sw: TStopWatch; begin sw := TStopWatch.StartNew; <dosomething> Writeln(Format(''runtime: %d ms'', [sw.ElapsedMilliseconds])); end;


Por lo que QueryPerformanceFrequency , el método más preciso es usar QueryPerformanceFrequency :

código:

var Freq, StartCount, StopCount: Int64; TimingSeconds: real; begin QueryPerformanceFrequency(Freq); QueryPerformanceCounter(StartCount); // Execute process that you want to time: ... QueryPerformanceCounter(StopCount); TimingSeconds := (StopCount - StartCount) / Freq; // Display timing: ... end;




clock_gettime() es la solución alta, que es precisa para nano segundos, también puedes usar rtdsc , que es preciso para el ciclo de la CPU, y por último puedes simplemente usar gettimeofday() .