Did I implement clock drift properly?
I couldn't find any clock drift RNG code for Windows anywhere so I attempted to implement it myself. I haven't run the numbers through ent
or DIEHARD
yet, and I'm just wondering if this is even remotely correct...
void QueryRDTSC(__int64* tick) {
__asm {
xor eax, eax
cpuid
rdtsc
mov edi, dword ptr tick
mov dword ptr [edi], eax
mov dword ptr [edi+4], edx
}
}
__int64 clockDriftRNG() {
__int64 CPU_start, CPU_end, OS_start, OS_end;
// get CPU ticks -- uses RDTSC on the Processor
QueryRDTSC(&CPU_start);
Sleep(1);
QueryRDTSC(&CPU_end);
// get OS ticks -- uses the Motherboard clock
QueryPerformanceCounter((LARGE_INTEGER*)&OS_start);
Sleep(1);
QueryPerformanceCounter((LARGE_INTEGER*)&OS_end);
// CPU clock is ~1000x faster than mobo clock
// return raw
return ((CPU_end - CPU_start)/(OS_end - OS_start));
// or
// return a random number from 0 to 9
// return ((CPU_end - CPU_start)/(OS_end - OS_start)%10);
}
If you're wondering why I Sleep(1)
, it's because if I don't, OS_end - OS_start
returns 0
consistently (because of the bad timer resolution, I presume).
Basically, (CPU_end - CPU_start)/(OS_end - OS_start)
always returns around 1000
with a slight variation based on the entropy of CPU load, maybe temperature, quartz crystal vibration imperfections, etc.
Anyway, the numbers have a pretty decent distribu开发者_如何学编程tion, but this could be totally wrong. I have no idea.
Edit: According to Stephen Nutt, Sleep(1)
may not be doing what I'm expecting, so instead of Sleep(1)
, I'm trying to use:
void loop() {
__asm {
mov ecx, 1000
cylcles:
nop
loop cylcles
}
}
The Sleep function is limited by the resolution of the system clock, so Sleep (1)
may not be doing what you want.
Consider some multiplication to increase the range. Then use the result to seed a PRNG.
精彩评论