Как найти скорость процессора?

Материал из DRKB

Как найти скорость процессора?[править | править код]

Пример взят из рассылки: СообЧА. Программирование на Delphi (http://Subscribe.Ru/catalog/comp.soft.prog.delphi2000)


function GetCPUSpeed: Double;
const
  DelayTime = 500;
var
  TimerHi: DWORD;
  TimerLo: DWORD;
  PriorityClass: Integer;
  Priority: Integer;
begin
  PriorityClass := GetPriorityClass(GetCurrentProcess);
  Priority := GetThreadPriority(GetCurrentThread); 
  SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
  Sleep(10);
  asm
    DW 310Fh // rdtsc
    MOV TimerLo, EAX
    MOV TimerHi, EDX
  end;
  Sleep(DelayTime);
  asm
    DW 310Fh // rdtsc
    SUB EAX, TimerLo
    SBB EDX, TimerHi
    MOV TimerLo, EAX
    MOV TimerHi, EDX
  end;
  SetThreadPriority(GetCurrentThread, Priority);
  SetPriorityClass(GetCurrentProcess, PriorityClass);
  Result := TimerLo / (1000.0 * DelayTime);
end;

// Usage ...

LabelCPUSpeed.Caption := Format('CPU speed: %f MHz', [GetCPUSpeed]);


Source: Взято с Vingrad.ru http://forum.vingrad.ru
ID: 01415



function GetCPUSpeed: real; 

  function IsCPUID_Available: Boolean; assembler; register; 
  asm 
            PUSHFD                { прямой доступ к флагам невозможен, только через стек }
            POP    EAX            { флаги в EAX } 
            MOV    EDX,EAX        { сохраняем текущие флаги }
            XOR    EAX,$200000    { бит ID не нужен }
            PUSH    EAX           { в стек } 
            POPFD                { из стека в флаги, без бита ID } 
            PUSHFD                { возвращаем в стек }
            POP    EAX            { обратно в EAX } 
            XOR    EAX,EDX        { проверяем, появился ли бит ID }
            JZ      @exit         { нет, CPUID не доступен }
            MOV    AL,True        { Result=True } 
            @exit: 
  end; 

  function hasTSC: Boolean; 
  var 
    Features: Longword; 
  begin 
    asm 
              MOV    Features,0    { Features = 0 } 

              PUSH    EBX 
              XOR    EAX,EAX 
              DW      $A20F 
              POP    EBX 

              CMP    EAX,$01 
              JL      @Fail 

              XOR    EAX,EAX 
              MOV    EAX,$01 
              PUSH    EBX 
              DW      $A20F 
              MOV    Features,EDX 
              POP    EBX 
              @Fail: 
    end; 

    hasTSC := (Features and $10) <> 0; 
  end; 

const 
  DELAY = 500; 
var 
  TimerHi, TimerLo: Integer; 
  PriorityClass, Priority: Integer; 
begin 
  Result := 0; 
  if not (IsCPUID_Available and hasTSC) then Exit; 
  PriorityClass := GetPriorityClass(GetCurrentProcess); 
  Priority := GetThreadPriority(GetCurrentThread); 

  SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS); 
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL); 

  SleepEx(10, FALSE); 

  asm 
            DB      $0F           { $0F31 op-code for RDTSC Pentium инструкции } 
            DB      $31           { возвращает 64-битное целое (Integer) } 
            MOV    TimerLo,EAX 
            MOV    TimerHi,EDX 
  end; 

  SleepEx(DELAY, FALSE); 

  asm 
            DB      $0F           { $0F31 op-code для RDTSC Pentium инструкции } 
            DB      $31           { возвращает 64-битное целое (Integer) } 
            SUB    EAX,TimerLo 
            SBB    EDX,TimerHi 
            MOV    TimerLo,EAX 
            MOV    TimerHi,EDX 
  end; 

  SetThreadPriority(GetCurrentThread, Priority); 
  SetPriorityClass(GetCurrentProcess, PriorityClass); 
  Result := TimerLo / (1000 * DELAY); 
end;


Source: Взято из http://forum.sources.ru
ID: 01416



const 
  ID_BIT = $200000; // EFLAGS ID bit 

function GetCPUSpeed: Double; 
const 
  DelayTime = 500; 
var 
  TimerHi, TimerLo: DWORD; 
  PriorityClass, Priority: Integer; 
begin 
  try 
  PriorityClass := GetPriorityClass(GetCurrentProcess); 
  Priority := GetThreadPriority(GetCurrentThread); 

  SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS); 
  SetThreadPriorit(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL); 

  Sleep(10); 
  asm 
    dw 310Fh // rdtsc 
    mov TimerLo, eax 
    mov TimerHi, edx 
  end; 
  Sleep(DelayTime); 
  asm 
    dw 310Fh // rdtsc 
    sub eax, TimerLo 
    sbb edx, TimerHi 
    mov TimerLo, eax 
    mov TimerHi, edx 
  end; 

  SetThreadPriority(GetCurrentThread, Priority); 
  SetPriorityClass(GetCurrentProcess, PriorityClass); 

  Result := TimerLo / (1000.0 * DelayTime); 
  except
  end; 
end; 


procedure TForm1.Button1Click(Sender: TObject); 
var
  cpuspeed: string; 
begin 
  cpuspeed := Format('%f MHz', [GetCPUSpeed]); 
  edit1.text := cpuspeed; 
end;


Source: Взято из http://forum.sources.ru
ID: 01417



function RdTSC : int64; register; 
asm 
  db   $0f, $31 
end;                                                  

function GetCyclesPerSecond : int64; 
var 
  hF, T, et, sc : int64; 
begin 
  QueryPerformanceFrequency(hF); // HiTicks / second 
  QueryPerformanceCounter(T); // Determine start HiTicks 
  et := T + hF; // (Cycles are passing, but we can still USE them!) 
  sc := RdTSC; // Get start cycles 
  repeat // Use Hi Perf Timer to loop for 1 second 
    QueryPerformanceCounter(T); // Check ticks NOW 
  until (T >= et); //  Break the moment we equal or exceed et 
  Result := RdTSC - sc; // Get stop cycles and calculate result 
end;


Source: Взято из http://forum.sources.ru
ID: 01418



Данная тема уже обсуждалась, но у меня есть своя реализация сабжа. Начиная с Pentium MMX, Intel ввели в процессор счетчик тактов на 64 бита (Присутствуэт точно и в К6). Для того чтобы посотреть на его содержание, была введена команда "rdtsc" (подробное описание в интеловской мануале). Эту возможность можно использовать для реализации сабжа. Посоку Делфя не вкурсе насчет rdtsc, то пришлось юзать опкод (0F31). Привожу простенький примерчик юзания, Вы уж извините - немножко кривоват получился, да и ошибка компалера какая-то вылезла :( (V4 Bld5.104 Upd 2). Кому интересно, поделитесь своими соображениями по этому поводу. Особенно интерисует работа в режиме когда меняется частота процессора (Duty Cycle, StandBy).


// (C) 1999 ISV
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics,
  Controls, Forms,Dialogs,  StdCtrls, Buttons, ExtCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    Label2: TLabel;
    Label3: TLabel;
    Button1: TButton;
    Button2: TButton;
    Label4: TLabel;
    procedure Timer1Timer(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  public
    { Public declarations }
    Counter: Integer; // Счетчик срабатывания таймера
    Start: Int64; // Начало роботы
    Previous: Int64; // Предыдущее значение
    PStart, PStop: Int64; // Для примера выч. времени
    CurRate: Integer; // Текущая частота проца
    function GetCPUClick: Int64;
    function GetTime(Start, Stop: Int64): Double;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

// Функция работает на пнях ММХ или выше а
// также проверялась на К6
function TForm1.GetCPUClick: Int64;
begin
  asm
    db  0fh,31h
    // Опкод для команды rdtsc
    // mov dword ptr result,eax
    // mov dword ptr result[4],edx
  end;
  // Не смешно :(. Без ?той штуки
  // Компайлер выдает Internal error C1079
  Result := Result;
end;

// Время в секундах между старт и стоп
function TForm1.GetTime(Start, Stop: Int64): Double;
begin
  try
    Result := (Stop-Start)/CurRate
  except
    Result := 0;
  end;
end;

// Обработчик таймера считает текущую частоту, выводит ее, а также
// усредненную частоту, текущий такт с момента старта процессора.
// При постоянной частоте процессора желательно интервал братьпобольше
// 1-5с для точного прощета частоты процессора.
procedure TForm1.Timer1Timer(Sender: TObject);
var
  i: Int64;
begin
  i := GetCPUClick;
  if Counter = 0 then
    Start := i
  else
  begin
    Label2.Caption := Format('Частота общая:%2f', [(i-Start)/(Counter*Timer1.Interval*1000)]);
    Label3.Caption := Format('Частота текущая:%2f', [(i-Previous)/(Timer1.Interval*1000)]);
    CurRate := Round(((i-Previous)*1000)/(Timer1.Interval));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  PStart := GetCPUClick;
end;

// Останавливаем отсчет времени и показуем соко
// прошло секунд
procedure TForm1.Button2Click(Sender: TObject);
begin
  PStop := GetCPUClick;
  Label4.Caption := Format('Время между нажатиями:%gсек', [GetTime(PStart, PStop)]);
end;

end.


Проверялось под еНТями на Пне 2 333.


Source: http://delphiworld.narod.ru/
ID: 01419



uses registry;

function GetCpuMhz: Word;
begin
  with TRegistry.Create do
  begin
    RootKey := HKEY_LOCAL_MACHINE;
    OpenKey('\hardware\description\system\centralprocessor\0\', False);
    Result := ReadInteger('~mhz');
    Free;
  end;
end;


Source: http://delphiworld.narod.ru/
ID: 01420