Hi,

I want to use the rtdsc instruction, but an intel documentation explain that with CPU as PII, PIII, ... it is better to use a "serializing instruction" just before to use rtdsc instruction.

They give an example of "serializing instruction" : cpuid
They say it is a complex instruction, which takes a lot of cycles to complete... Is there an another "serializing instruction" which takes less cycles ???? (which work on AMD too)

Moreover, is it possiblie, with an instruction, to obtain the CPU speed, without using average function as Sleep and the combination Sleep and rtdsc, etc ? (which work on AMD too).
Indeed the cpuid instruction gives a lot of detail about the CPU, but not the speed.

Thanks for your help.
Posted on 2002-02-28 06:05:51 by DarkEmpire
Hi DarkEmpire,
Out of my memory, the other serializing instructions (such as WBINVD, LIDT, LMSW, WRMSR, MOV to CRx, etc..) are all privileged instructions, so you "can't" use them anyway, not in ring3 at least. RDPMC however is *optionally* executable in ring 3 (check your OS, anyway you've to set the PCE flag in CR4, but you must do that from ring0 (or with OS emulation, from ring3)), and is serializing as well. That could be the best solution for you, but perhaps XOR EAX,EAX .. CPUID will be faster anyway. But how much? Nothing.. because its slowness derives from the fact that "serializing" means that all pending operations (including memory write buffers, but not write cache flushes.. for that use WBINVD) have to be completed before execution continues. So it's not CPUID which is slow, but the very concept of serializing. And unfortunately that is very necessary.

I hope that helped, if not I'm here to reply to other questions (if you want).
Greets,
Maverick

PS: I checked the volume 3 of the Intel manuals, and also IRET and RSM are non privileged serializing instructions, not a big deal anyway!
Posted on 2002-02-28 07:22:17 by Maverick
I forgot to reply to the 2nd part:


Moreover, is it possiblie, with an instruction, to obtain the CPU speed, without using average function as Sleep and the combination Sleep and rtdsc, etc ? (which work on AMD too).
No.. but IMHO one of the best (i.e. precise, if precision is important for you) ways, in Windows, is to use QueryPerformanceFrequency() and QueryPerformanceCounter() .. do not use sleep()!!
What I personally do is using those, and update CPU MHz from time to time, to get a more accurate and more accurate value (then saved to disk). A rough estimate is done at the begin of execution, to see if the user changed his MHz, but also during execution, for those portable PC's (and not) where one can change the CPU clock rate at "run time", with a switch or equivalent.

Thanks for your help.
You're Welcome :)

Greets,
Maverick
Posted on 2002-02-28 07:27:42 by Maverick
Thanks a lot for your help...

It is very helpfull that a replies does not only take 1 line :)

But , i hope you won't think i am a big newbie :tongue: but how do you use QueryPerformanceFrequency() and QueryPerformanceCounter() to obtain the cpu speed ?? these fonctions can give the time of execution ... But how do you calculate CPU speed from that ??

Thanks.
Posted on 2002-02-28 15:13:58 by DarkEmpire
Don't worry pal, I was a newbie too.. I wish somebody helped at that time.. but I didn't even had the luck of things like modems.

So, you check the rate by using QueryPerformanceFrequency.. it will be about 1192500 Hz on standard PC's (but if you wanna write decent code you must *not* rely on things like this).
So, thanks to the value of above, you know how to wait e.g. 0.1 seconds.. i.e. check QueryPerformanceCounter until 119250 ticks passed.
Just before this 0.1 sleep-like loop, you saved the TSC value of the CPU, by using the assembly instruction RDTSC. You do it again after your 0.1 seconds sleep pause.
The difference of the two TSC values, multiplied by 10 (i.e. divided by that 0.1 seconds value) gives your CPU's MHz.
If you will take care of save somewhere the first value you got with QueryPerformanceFrequency, *and* the first TSC value you got, you will be able to reuse both as a comparison, after (for example) 1 minute, to get a much more precise MHz mark (really, a Hz one).

BTW: on the Amiga I coded a public domain thermometer by using a similar technique. It calculated (didn't take one minute though, but much less) the Hz with so much precision that one could notice the increase in temperature of the expansion board's CPU XTAL (68020,68030,68040 or 68060) against the video chip XTAL, which was much cooler and running at a constant temperature. :) Depending on the temperature, there was a difference of up to 1000,1500 Hz. :)

Funny times..

Greets,
Maverick
Posted on 2002-02-28 16:59:12 by Maverick
PS: this one:

If you will take care of save somewhere the first value you got with QueryPerformanceFrequency, *and* the first TSC value you got, you will be able to reuse both as a comparison, after (for example) 1 minute, to get a much more precise MHz mark (really, a Hz one).


should read instead:

If you will take care of saving somewhere the first value you got from QueryPerformanceCounter, *and* the first TSC value you got from RDTSC, you will be able to reuse both as a comparison, after (for example) 1 minute, to get a much more precise MHz mark (really, a Hz one).
Posted on 2002-02-28 17:02:05 by Maverick
Thanks a lot for your help
Posted on 2002-03-02 15:09:42 by DarkEmpire
You're welcome. :)
Posted on 2002-03-02 16:11:41 by Maverick
I just wrote a quick one -- Hope it helps




.686
.model flat, stdcall
option casemap :none ; case sensitive

include \masm32\include\windows.inc

include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\debug.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib

.data

MsgTitle db 'CPU Speed',0
CpuSpeed db 'CPU Speed = %lu mhz',0
MsgBuffer db 30 dup (0)

.code

start:
xor eax,eax
CPUID
RDTSC ;Intel says that you should not use the
;the first rdtsc... so throw it away

CPUID
RDTSC ;db 0fh,31h
mov ebx,eax
invoke Sleep,1000
RDTSC ;db 0fh,31h
sub eax,ebx
sub eax,8
xor edx,edx
mov ecx,1000000
div ecx
invoke wsprintfA, ADDR MsgBuffer , ADDR CpuSpeed, eax
invoke MessageBoxA, 0 ,ADDR MsgBuffer , ADDR MsgTitle, 0
invoke ExitProcess , 0

end start


Posted on 2002-03-02 17:01:46 by Sliver
Here is a nice text explaining how to time using RDTSC:
http://cedar.intel.com/software/idap/media/pdf/rdtscpm1.pdf
Posted on 2002-03-02 17:30:42 by bitRAKE