计算例程的速度?
什么是确定处理例程花费多长时间的最好和最准确的方法,例如函数过程?
我问,因为我目前正在试图优化我的应用程序中的几个function,当我testing的变化很难确定只是通过看它,如果有任何改进。 所以,如果我能够返回一个准确的或接近准确的时间来处理一个例程,那么对代码的更改做得如何,我会有一个更清晰的认识。
我考虑过使用GetTickCount,但我不确定这是否接近准确?
有一个可重用的函数/过程来计算一个例程的时间是非常有用的,并使用如下所示:
// < prepare for calcuation of code ... ExecuteSomeCode; // < code to test ... // < stop calcuating code and return time it took to process
我期待听到一些build议。
谢谢。
克雷格。
据我所知,最准确的方法是使用QueryPerformanceFrequency :
码:
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;
试试Eric Grange的采样分析器 。
从Delphi 6开始,您可以使用x86 Timestamp计数器。
这个计数CPU周期,在一个1 Ghz的处理器,每个计数需要一个纳秒。
不能比这更准确。
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;
在x64下面的代码是更准确的,因为它不受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
执行代码之前和之后,使用上面的代码获取时间戳。
最准确的方法可能和容易。
请注意,您需要至less运行一次testing10次以获得良好的结果,第一遍caching将会变冷,随机硬盘读取和中断可能会导致您的计时结束。
因为这件事情是如此的准确,所以如果你只是第一次跑步,它会给你错误的想法。
为什么你不应该使用QueryPerformanceCounter()
QueryPerformanceCounter()
给出相同的时间量,如果CPU变慢,它会补偿CPU的阻塞。 虽然RDTSC会给你相同数量的周期,如果你的CPU减速由于过热或什么。
所以如果你的CPU开始运行并且需要压低, QueryPerformanceCounter()
会说你的程序需要更多的时间(这是误导性的),而RDTSC会说它需要相同数量的周期(这是准确的) 。
这是你想要的,因为你对你的代码使用的CPU周期数量感兴趣,而不是挂钟时间。
从最新的英特尔文档: http ://software.intel.com/en-us/articles/measure-code-sections-using-the-enhanced-timer/?wapkw=%28rdtsc%29
使用处理器时钟
这个计时器是非常准确的。 在具有3GHz处理器的系统上,该计时器可以测量持续时间小于1纳秒的事件。 […]如果频率在目标代码运行时发生变化,则最终读数将是多余的,因为初始读数和最终读数不是使用相同的时钟频率。 在这段时间内发生的时钟滴答的数量是准确的 ,但经过的时间将是未知的。
什么时候不用RDTSC
RDTSC对于基本时序很有用。 如果您在一台CPU机器上计算multithreading代码,RDTSC将正常工作。 如果您有多个CPU,则startcount可能来自一个CPU,而来自另一个CPU的endcount。
因此,不要使用RDTSC在多CPU机器上计算multithreading代码。 在单CPU机器上工作正常,或在多CPU机器上的单线程代码,这也很好。
还要记住RDTSC计算CPU周期。 如果有什么需要时间,但不使用CPU,比如磁盘IO或networking,那么RDTSC不是一个好的工具。
但是文档说RDTSC在现代CPU上是不准确的
RDTSC 不是跟踪时间的工具,它是跟踪CPU周期的工具。
为此,它是唯一准确的工具。 跟踪时间的例程在现代CPU上是不准确的,因为CPU时钟不像以前那样是绝对的。
您没有指定您的Delphi版本,但Delphi XE在单元诊断中声明了TStopWatch。 这将允许您以合理的精度测量运行时间。
uses Diagnostics; var sw: TStopWatch; begin sw := TStopWatch.StartNew; <dosomething> Writeln(Format('runtime: %d ms', [sw.ElapsedMilliseconds])); end;
我问,因为我目前正在试图优化几个function
认为衡量是如何找出优化的东西是很自然的,但是有一个更好的方法。
如果某件事花费了足够多的时间(F)来进行优化,那么如果你只是随意暂停它,那么F就是你在行为中捕捉它的概率。 这样做几次,你就会明白为什么这样做,直到确切的代码行。
更多关于这一点。 这是一个例子。
修复它,然后做一个全面的测量,看看你有多less节省,应该是关于F.冲洗和重复。
以下是我为处理一个函数的持续时间而做的一些程序。 我把它们放在一个我称之为uTesting
的单元中,然后在testing过程中抛出使用子句。
宣言
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声明
var Time : array[1..100] of TDateTime;
履行
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;
clock_gettime()
是精确到纳秒级的高级解决scheme,您也可以使用rtdsc
,这对于CPU周期是精确的,最后您可以简单地使用gettimeofday()
。