Board index » delphi » detecting the CPU speed

detecting the CPU speed

i'd like to have my BP app incorporate different levels of features
based on the speed of the user's CPU.  it's a heavy-graphic app, so i'm
thinking the minimum system req. is a P-133.  i'd like to be able to
determine the mhz, from 60 to 450.  i've seen lots of chip detectors,
that can tell you if it's a 386, 486, whatever, but that's not really
usefull for my purposes.  

any help greatly appreciated.

please cc to my email if posting a response, thanks.

 

Re:detecting the CPU speed


Quote
Tim wrote:

> i'd like to have my BP app incorporate different levels of features
> based on the speed of the user's CPU.  it's a heavy-graphic app, so i'm
> thinking the minimum system req. is a P-133.  i'd like to be able to
> determine the mhz, from 60 to 450.  i've seen lots of chip detectors,
> that can tell you if it's a 386, 486, whatever, but that's not really
> usefull for my purposes.

Windows? If not:

Var Timer18:Integer absolute $0040:$006C;

Function GetSpeed : Longint;
Var SavTimer : Integer;
    Cntr     : Longint;
Begin
  Cntr := 0;
  SavTimer := Timer18;
  Repeat Until SavTimer <> Timer18;
  SavTimer := Timer18;
  Repeat
    Inc(Cntr);
  Until SavTimer <> Timer18;
  GetSpeed := Cntr;
End;

Franz Glaser

Re:detecting the CPU speed


Ing. Franz Glaser schrieb:

Quote
> Var Timer18:Integer absolute $0040:$006C;

> Function GetSpeed : Longint;
> Var SavTimer : Integer;
>     Cntr     : Longint;
> Begin
>   Cntr := 0;
>   SavTimer := Timer18;
>   Repeat Until SavTimer <> Timer18;
>   SavTimer := Timer18;
>   Repeat
>     Inc(Cntr);
>   Until SavTimer <> Timer18;
>   GetSpeed := Cntr;
> End;

I don't really understand... Are you assuming that Inc(Cntr) just takes a
single clock cycle to execute? So that, therefore, after the loop, Cntr
contains the number of clock cycles after a second? But the loop itself also
takes some time, the comparison for example.

Re:detecting the CPU speed


In comp.lang.pascal.borland, Frederic uttered:

Quote
>Ing. Franz Glaser schrieb:

>> Var Timer18:Integer absolute $0040:$006C;

>> Function GetSpeed : Longint;
>> Var SavTimer : Integer;
>>     Cntr     : Longint;
>> Begin
>>   Cntr := 0;
>>   SavTimer := Timer18;
>>   Repeat Until SavTimer <> Timer18;
>>   SavTimer := Timer18;
>>   Repeat
>>     Inc(Cntr);
>>   Until SavTimer <> Timer18;
>>   GetSpeed := Cntr;
>> End;

>I don't really understand... Are you assuming that Inc(Cntr) just takes a
>single clock cycle to execute? So that, therefore, after the loop, Cntr
>contains the number of clock cycles after a second? But the loop itself also
>takes some time, the comparison for example.

The solution posted by Franz looks at a location that holds the timer
information.

The first repeat .. until loop waits until the second changes and the
second loop increments Cntr until the second changes again. You now have
a Cntr longint variable that tells you, reasonably accurately under DOS,
how many increments of Cntr took place in one second. This should give
you the relevant information on how much to delay:

if Cntr =  2000 then delay for period of time 10
if Cntr =  4000 then delay for period of time  5
if Cntr = 20000 then delay for period of time  1
etc.

The loop itself will indeed take some time. It may be preferable to add
a number of NOP statements within the second repeat loop.

For TP6 and 7 use
asm
   nop;  {as many as you want}
end;

For TP5 and 5.5 use
inline($90); {again as many as you want}

--
Pedt Scragg

No-one is completely useless, they can always be a bad example.

Re:detecting the CPU speed


JRS:  In article <363A5769.B2FE0...@eunet.at> of Sat, 31 Oct 1998
01:18:49 in comp.lang.pascal.borland, Ing. Franz Glaser <meg-

Quote
gla...@eunet.at> wrote:
>Var Timer18:Integer absolute $0040:$006C;

>Function GetSpeed : Longint;
>Var SavTimer : Integer;
>    Cntr     : Longint;
>Begin
>  Cntr := 0;
>  SavTimer := Timer18;
>  Repeat Until SavTimer <> Timer18;
>  SavTimer := Timer18;
>  Repeat
>    Inc(Cntr);
>  Until SavTimer <> Timer18;
>  GetSpeed := Cntr;
>End;

Or, perhaps,
for J := 0 to 1 do begin
  Cntr := 0;
  SavTimer := Timer18;
  Repeat
    Inc(Cntr);
  Until SavTimer <> Timer18;
end ;

Actually, it would be better in principle to have Timer18 a word or a
longint, if it is used elsewhere (though here, a byte will do); and one
can use a pointer for DPMI work.

Alas, I cannot now examine the code produced by BP from Pascal in News
as readily as before.

--
John Stockton, Surrey, UK.    j...@merlyn.demon.co.uk    Turnpike v4.00    MIME.
  Web <URL: http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.

Re:detecting the CPU speed


In article: <363A0411.94C26...@xmission.com>  Tim <x...@xmission.com> writes:

Quote

>i'd like to have my BP app incorporate different levels of features
>based on the speed of the user's CPU.  it's a heavy-graphic app,

A Heavy graphic application might (should) also want to measure the speed of the
graphics card, since the speed from one card to the next can vary enormously.
You could do this by accessing the video RAM within your CPU timing loop, in
which case it will give you some sort of composite speed rating, or you might
want to perform a separate video card speed test.

In either case relative timings (to a known machine and video card) will
probably suffice; you probably don't need absolute timing figures.

Jay
--

 -----------------------------------------
| Jason Burgon - author of Graphic Vision |
| g...@jayman.demon.co.uk                   |
| http://www.jayman.demon.co.uk           |
 -----------------------------------------

Re:detecting the CPU speed


In article <363AF092.A15A...@rz-online.de>,

Quote
Frederic  <frede...@rz-online.de> wrote:
>Ing. Franz Glaser schrieb:

>> Var Timer18:Integer absolute $0040:$006C;

>> Function GetSpeed : Longint;
>> Var SavTimer : Integer;
>>     Cntr     : Longint;
>> Begin
>>   Cntr := 0;
>>   SavTimer := Timer18;
>>   Repeat Until SavTimer <> Timer18;
>>   SavTimer := Timer18;
>>   Repeat
>>     Inc(Cntr);
>>   Until SavTimer <> Timer18;
>>   GetSpeed := Cntr;
>> End;

>I don't really understand... Are you assuming that Inc(Cntr) just takes a
>single clock cycle to execute?

No, there is no such assumption.

Quote
> So that, therefore, after the loop, Cntr
>contains the number of clock cycles after a second? But the loop itself also
>takes some time, the comparison for example.

You need to calibrate the routine. Also it might be good to take more
than one measure especially if one runs some multitasking system.

Osmo

Re:detecting the CPU speed


In article <12219018...@jayman.demon.co.uk>,

Quote
Jason Burgon <Ja...@jayman.demon.co.uk> wrote:
>In article: <363A0411.94C26...@xmission.com>  Tim <x...@xmission.com> writes:

>>i'd like to have my BP app incorporate different levels of features
>>based on the speed of the user's CPU.  it's a heavy-graphic app,

>A Heavy graphic application might (should) also want to measure the speed of the
>graphics card, since the speed from one card to the next can vary enormously.
>You could do this by accessing the video RAM within your CPU timing loop, in
>which case it will give you some sort of composite speed rating, or you might
>want to perform a separate video card speed test.

How about something radical: Letting the user decide the level. What is
fast enough is very subjective and a programmer cannot decide it for
all users. I would be really annoyed if I would either lose some
features or have to suffer some needless effects just because some
programmer thought that I should do so because I have some specific CPU.

Osmo

Re:detecting the CPU speed


:>Ing. Franz Glaser schrieb:
:>> Var Timer18:Integer absolute $0040:$006C;
:>> Function GetSpeed : Longint;

I made some testing of the posted code. Unfortunately, it turned out
give too volatile results. I also tried averages. The range of the
results varied from (a scaled) 100.0 to 200.0. This I have to take
as "problem not actually yet solved".

I say this only constructively! It would have been nice to have this
as a FAQ, but it is not ripe yet.

   All the best, Timo

....................................................................
Prof. Timo Salmi   Co-moderator of news:comp.archives.msdos.announce
Moderating at ftp:// & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance  ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/>  ; FIN-65101,  Finland

Spam foiling in effect.  My email filter autoresponder will return a
required email password to users not yet in the privileges database.
Advice on spam foiling at http://www.uwasa.fi/~ts/info/spamfoil.html

Re:detecting the CPU speed


About one and a half years ago I wrote a routine which determines the
CPU speed for my Acorn Atom emulator. For most processors it comes
pretty close (e.g. for 486 DX40 is gives values about 38-40, for P120
values 118-121, for P233 values 231-233, depending whether the program
is run in native DOS mode or in a DOS box under Windows).

It has been written with TP7.0. Execution time is hardly noticable.
The routine uses PIT counter 2 at port 0042h. It allocates memory (about
64 kB) and fills that with CLCs (Clear Carry Flag), an instruction that
*always* takes 2 cycles and that is not affected by Pentium's U- nor
V-pipe, on Intel and AMD processors. Unfortunately it does not work well
with Cyrix processors, it gives a value about 3 times too high.

Here's the code. Near label @Timer2 the DBs and DW form the instruction
CALL FAR [CS:@SUBR], which unfortunately cannot be entered as assembly.

Kind regards,
Wouter Ras.

-----------------------------------------------------

function GetCPUSpeed: Word;
var
  P: Pointer;
  POfs, PSeg: Word;
  T: LongInt;
  W: Word;
  I: Byte;
begin
  GetMem(P, $FFF8);
  POfs := Ofs(P^);
  PSeg := Seg(P^);
  T := 0;
  for I := 1 to 20 do
  begin
    asm;
               MOV   DI,WORD PTR POfs
               MOV   WORD PTR @SUBR[$00],DI
               MOV   ES,WORD PTR PSeg
               MOV   WORD PTR @SUBR[$02],ES
               CLD
               MOV   AX,$F8F8      {2xCLC}
               MOV   CX,$FFF0/2
               REPZ
               STOSW
               MOV   AL,$CB        {RETF}
               STOSB
               NOP
               IN    AL,$61
               PUSH  AX
               CLI
               AND   AL,$FE
               OUT   $61,AL
               MOV   AL,$B2
               OUT   $43,AL
               MOV   AL,$00
               OUT   $42,AL
               OUT   $42,AL
               IN    AL,$61
               OR    AL,$01
               AND   AL,$FD
               OUT   $61,AL
               MOV   CX,$0003
    @TIMER2:   NOP
               DB    $2E,$FF,$1E
               DW    OFFSET @SUBR
               NOP
               LOOP  @TIMER2
               IN    AL,$61
               AND   AL,$FE
               OUT   $61,AL
               MOV   AL,$B0
               OUT   $43,AL
               IN    AL,$42
               MOV   AH,AL
               IN    AL,$42
               XCHG  AL,AH
               NEG   AX
               MOV   WORD PTR W,AX
               POP   AX
               OUT   $61,AL
               STI
               JMP   @TIMER1
    @SUBR:     DD    $00000000
    @TIMER1:
    end;
    Inc(T, LongInt(W));
  end;
  FreeMem(P, $FFF8);
  T := T div 20;
  W := 460680 div T;
  asm;
               MOV   AX,WORD PTR W
               MOV   BX,AX
    @TIMER5:   SUB   BX,+33
               JC    @TIMER4
               INC   AX
               JMP   @TIMER5
    @TIMER4:   MOV   WORD PTR @Result,AX
  end;
end;

Re:detecting the CPU speed


JRS:  In article <71tai4$...@majakka.uwasa.fi> of Fri, 6 Nov 1998
00:58:12 in comp.lang.pascal.borland, Timo Salmi <t...@UWasa.Fi> wrote:

Quote
>I made some testing of the posted code. Unfortunately, it turned out
>give too volatile results. I also tried averages. The range of the
>results varied from (a scaled) 100.0 to 200.0. This I have to take
>as "problem not actually yet solved".

>I say this only constructively! It would have been nice to have this
>as a FAQ, but it is not ripe yet.

You might start with the parts about what won't work well - presumably
unreliable in a Windows DOS Box - *perhaps* one should wait more than
one tick before starting timing, to ensure full cacheing on a system
where the code may be swapped out.

In pure DOS, I do believe that one can get meaningful results; though if
you have, say, a modern portable with resident code monitoring whether
either the battery or the user appears to be exhausted, or maybe one of
those PCs with non-independent Video RAM whose effective speed is
affected by the picture scanning, ...

There's a *bit* at my  http://www.merlyn.demon.co.uk/pas-time.htm#Misuse

--
John Stockton, Surrey, UK.    j...@merlyn.demon.co.uk    Turnpike v4.00    MIME.
  Web <URL: http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
  Correct 4-line sig. separator is as above, a line precisely "-- " (SoRFC1036)
  Do not Mail News to me.    Before a reply, quote with ">" or "> " (SoRFC1036)

Re:detecting the CPU speed


Quote
On Fri, 30 Oct 1998 11:23:13 -0700, Tim <x...@xmission.com> wrote:
>i'd like to have my BP app incorporate different levels of features
>based on the speed of the user's CPU.  it's a heavy-graphic app, so i'm
>thinking the minimum system req. is a P-133.  i'd like to be able to
>determine the mhz, from 60 to 450.  i've seen lots of chip detectors,
>that can tell you if it's a 386, 486, whatever, but that's not really
>usefull for my purposes.  

Just like to add some points to this thread for consideration.

I believe it is not possible to obtain any accurate indication of cpu
speed since, from 8088 processors, the instruction queue will
introduce errors into any loop type estimation procedure. Thing have
become even worse with the implementation of internal and external
caching. If you look at the instruction list for any cpu, you will
notice a range of clock cycles quoted for every instruction. The
situation for PCs is not the same as it was in the days of the Z80
where timing could be accurately calculated from the instructions
executed. Instruction counting loops are just not accurate of which
you should already be aware. The delay procedure in the CRT unit is
the best example and everyone knows that is not very accurate at all
(no matter what machine).

On the subject of graphics performance, I know from experience that
above a certain processor speed (eg, 386SX-16) video card band-width
will be the {*word*109} performance factor. By way of explanation, I
wrote a procedure which updated a small window at the rate of 25 per
second. The procedure runs absolutely flat out with no delays or
adjustments for the cpu and it appears exactly the same on my new
K6-255 as it did on the 386SX-16 because I am using the same 16bit ISA
video card.

I submit this for your consideration and appologise for not having a
worthwhile suggestion for a solution.

Bill.
Bill.
---------------------------------
Remove "nospam." for direct reply
---------------------------------

Other Threads