flat assembler
Message board for the users of flat assembler.
Index
> Windows > Question: How do I get real millisecond acuracy. |
Author |
|
f0dder 07 Aug 2008, 09:57
Don't do rdtsc - this leads to problems on AMD dualcore machines if your thread gets schedules to another core.
Your best bet is probably timeBeginPeriod() and some manual time polling... but this will obviously hog the CPU. Windows wasn't really written with realtime use in mind. What are you trying to do? Oh great, sucky phpBB can't handle parenthesis in URLs? Yay. I'll just leave the post formatted as-is |
|||
07 Aug 2008, 09:57 |
|
Madis731 07 Aug 2008, 10:39
The algorithm is relatively easy:
Code: rdtsc mov qword[time1],eax:edx ... ... rdtsc sub eax:edx,qword[time1] mov esi,[CPU_ticks_in_ms] ; 2.5GHz CPU has 2500000 here div esi ;OUT=eax ms The problem is knowing your CPU clock. Intel has algorithms to read this from cpuid, but AMD behaves differently. Intel also has an HPET on some newer boards if you can use it, but other manufactures don't etc. EDIT: The easiest way on non-HT, non-DC, non-IntelSpeedStep machines is to init your CPU_ticks_in_ms on program startup by measuring it to a known value. GetTickCount+1000 for example and then use it in other places of your program. Last edited by Madis731 on 07 Aug 2008, 10:50; edited 1 time in total |
|||
07 Aug 2008, 10:39 |
|
f0dder 07 Aug 2008, 10:46
Madis: again, DO NOT USE RDTSC FOR TIMING!
It's OK if you want to profile a snippet of code, but you shouldn't use it for production-grade timing. There's the AMD dual-core bug (and no, not everybody will have AMDs fix/hack installed). And then there's the issue of speedstep and similar technologies... |
|||
07 Aug 2008, 10:46 |
|
Madis731 07 Aug 2008, 10:53
okay sorry (shame on me), there's a topic on GameDev: http://www.gamedev.net/community/forums/topic.asp?topic_id=321312
HPET I was talking about: http://en.wikipedia.org/wiki/High_Precision_Event_Timer |
|||
07 Aug 2008, 10:53 |
|
Tomasz Grysztar 07 Aug 2008, 11:24
What about local APIC timer?
|
|||
07 Aug 2008, 11:24 |
|
DJ Mauretto 07 Aug 2008, 17:57
Hello
Local APIC timer use Cpu bus clock + internal register as divider selectable , it's not compatible betwen different pc , then i don't think that OS like windows allow you to access to memory mapped APIC register. The only way is Windows API or write a kernel mode driver and use 8254 timer Note: if your software run only on your pc use this: mov ecx,Delay @@: loop @B It is the perfect timer better of RDTSC ,HPET, APIC and 8254 _________________ Nil Volentibus Arduum |
|||
07 Aug 2008, 17:57 |
|
Alphonso 07 Aug 2008, 18:30
Well maybe there's the windows high performance counters... As a very rough example
Code: include 'win32ax.inc' .code start: invoke QueryPerformanceFrequency,Freq cmp eax,0 je HPC_Not_Supported mov edx,dword [Freq+4] mov eax,dword [Freq] ;Freq = counts per second mov ebx,1000 div ebx cmp eax,10 jl Sub100us ;Resolution is less than 100us mov [msRes],eax ;counts per millisecond invoke QueryPerformanceCounter,StartTime mov ebx,dword [StartTime] add ebx,[msRes] ;ebx=Start time + 1ms in counts ;-------------------------------------------------------------------- @@: invoke QueryPerformanceCounter,StopTime mov eax,dword [StopTime] sub eax,ebx jl @b ;Check if 1ms has passed yet ;-------------------------------------------------------------------- mov edx,dword [StopTime+4] ;Check actual time mov eax,dword [StopTime] sub eax,dword [StartTime] sbb edx,dword [StartTime+4] mov ebx,1000000 mul ebx ;edx:eax = counts per microsecond mov ebx,dword [Freq] div ebx ;eax = number of microseconds invoke wsprintf,Result,'%d us',eax ;easy/lazy way Zzz... invoke MessageBox,NULL,Result,'Timing',MB_OK jmp @f Sub100us: invoke MessageBox,0,'<100us','Low Resolution',MB_OK jmp @f HPC_Not_Supported: invoke MessageBox,0,'No performance here..','Error',MB_OK @@: invoke ExitProcess,0 .end start .data Freq dq 0 StartTime dq 0 StopTime dq 0 msRes dd 0 Result rb 20 |
|||
07 Aug 2008, 18:30 |
|
r22 07 Aug 2008, 23:41
rxantos wrote: Is there a way to get real 1 millisecond accuracy (not 15 or 10 milliseconds) withing windows? Basically I need a delay of 1 to 2 miliseconds between 2 operations. One after another is too fast and waiting 15 milliseconds is too slow. OPTION 1 The SleepEx function in kernel32.dll will work. invoke SleepEx, 1, 0 Setting your process / threads priority class to real_time and affinity mask to 1 processor will help. This is the best you can do without a driver in windows user-land. OPTION 2 You could also try using the WINMM.DLL functions timeBeginPeriod timeEndPeriod timeSetEvent and the callback TimeProc |
|||
07 Aug 2008, 23:41 |
|
Madis731 08 Aug 2008, 07:05
The SleepEx is precise to about 1ms, but ONLY after 16ms which I think is the first increment - always! Thread priority and affinity doesn't help there.
When you already guarantee only one CPU, then you can read core clock cycles, which do not change. (Needs a driver) I think that Microsoft even tells on their site that their high-precision functions don't work that well, if you're not careful |
|||
08 Aug 2008, 07:05 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.