I can't believe I didn't check this earlier...
whatever "Nanoseconds" you are displaying, are not nanoseconds.
Check this out:
http://www.google.com/#q=1+millisecond+in+nanoseconds
Or this:
http://en.wikipedia.org/wiki/Orders_of_ ... %28time%29
"1,000,000,000 nanoseconds: 1 second"
So you have to redo some stuff...
Just as a quick example I used your source, tossed out the thread stuff as it tended to crash now and again here. (something with the asm in it probably)
I got rid of the delay procedure to reduce timing overhead.
Something interesting is that if I try for a 1ns delay, I never get much lower than 5000 something, which means QPC has quite a bit overhead (as has been noted by many coders before), timeGetTime_() has less overhead, and getTickCounts_() even less than that, obviously those have less accuracy.
You will never be able to get 1ns delays on any current computers I guess, due to the fact that a 2.1GHz is only able to do (on average I assume) 2.1 cycles per nanosecond, and QPC and even fetching RDTSC etc. uses more than 2.1 cycles.
What your source seems to display is microseconds rather than nanoseconds.
1 sec / 1000 = 1 millisecond
1 millisecond / 1000 = 1 microsecond
1 microsecond / 1000 = 1 nanosecond
Setting the
ns=1000000 to
ns=1 here results in an average of
5205 nanoseconds. And since my cores are 2.1GHz each that means I'd need over 1THz to get close to 1ns timings.
PS! Even commenting out the Delay(0) only shaves off down to an average of 3987.
PPS! Oh and on my system the QPC have a precision of 14MHz. (it uses a high precision clock crystal on the motherboard I assume)
Code: Select all
EnableExplicit
#CompareMilliSeconds = 1
Global mod.d,nano.d,freq.q
CompilerIf #CompareMilliSeconds
Global timecaps.TIMECAPS
timeGetDevCaps_(@timecaps, SizeOf(TIMECAPS))
timeBeginPeriod_(timecaps\wPeriodMin)
CompilerEndIf
Global sum1.q,sum2.q,ct.i,elt.q,mst.l,men.l,el.l,avg1.q,avg2.q,sta.q,sto.q
;We use a double modifier as that is faster than double division.
;1 nanosec = 1000000000 = 1GHz, QPF = counts per sec.
QueryPerformanceFrequency_(@freq)
mod=freq/1000000000
nano=1000000000/freq
OpenConsole()
Delay(100)
;Global mfreq = InitTimer(500)
;PrintN(Str(mfreq) + " MHz")
Define te.q, tn.q, mtime.q, ns.i
Repeat
ns=1000000 ;Should be ~1000000 nano seconds or 1ms
mtime=ns*mod ;convert from ns to QPC frequency.
QueryPerformanceCounter_(@sta)
CompilerIf #CompareMilliSeconds
mst = timeGetTime_()
CompilerEndIf
;Wait ns nanoseconds, not using a procedure as that would add overhead.
QueryPerformanceCounter_(@te)
Repeat
Delay(0) ;contextswitch, delay varies.
QueryPerformanceCounter_(@tn)
Until (tn-te)>=mtime ;We need to subtrack endtime by start time to avoid sign wrapping issues,
;just like we need to do with timeGetTime_(), ElapsedMilliseconds(), GetTickCount_() etc.
QueryPerformanceCounter_(@sto)
CompilerIf #CompareMilliSeconds
men=timeGetTime_()
CompilerEndIf
elt = (sto - sta)*nano ;convert from QPC frequency to ns
CompilerIf #CompareMilliSeconds
el = men - mst
PrintN(Str(elt) + " NanoSeconds " + Str(el) + " MilliSeconds")
CompilerElse
PrintN(Str(elt) + " NanoSeconds ")
CompilerEndIf
ct+1
sum1 + elt
sum2 + el
Until Inkey()
avg1 = sum1 / ct
CompilerIf #CompareMilliSeconds
avg2 = sum2 / ct
PrintN("Averages " + Str(avg1) + " NanoSeconds " + Str(avg2) + " Milliseconds")
CompilerElse
PrintN("Averages " + Str(avg1) + " NanoSeconds ")
CompilerEndIf
Input()
CompilerIf #CompareMilliSeconds
timeEndPeriod_(timecaps\wPeriodMin)
CompilerEndIf