【问题标题】:How to get CPU speed from Delphi 64 bit application (XE5)?如何从 Delphi 64 位应用程序 (XE5) 获得 CPU 速度?
【发布时间】:2014-02-13 14:35:04
【问题描述】:

我们正在使用 Delphi XE5 将我们的应用程序套件迁移到 64 位。在我们的关于框中,我们显示 CPU 速度。我们目前使用的例程是 32 位汇编,因此不会在 64 位下编译。

是否有本地方法可以从 Delphi 64 位中检索 CPU 速度?

【问题讨论】:

  • 我感觉 WMI 的答案即将到来,@RRUZ 你在哪里? :)
  • 可能重复,Find out the current frequency of the CPU。 x32 和 x64 的 WMI 接口相同。
  • 你想要每个核心的速度吗?你需要什么:实际的 CPU 速度还是宣传的速度?
  • 检查我的答案,我认为这正是你需要的:)

标签: delphi 64-bit delphi-xe5


【解决方案1】:

如果您的平台是 Windows,并且您想要宣传的 CPU 速度,那么您只需检查注册表中的 HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\~MHz DWORD 值:

program SO21757165;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Registry,
  Windows,
  System.SysUtils;

function GetCPUSpeed : String;

var
  Reg : TRegistry;

begin
 Reg := TRegistry.Create(KEY_QUERY_VALUE);
 try
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  if Reg.OpenKeyReadOnly('HARDWARE\DESCRIPTION\System\CentralProcessor\0') then
   begin
    Result := Format('CPU Speed is %dMHz', [Reg.ReadInteger('~MHz')]);
    Reg.CloseKey;
   end;
 finally
  Reg.Free;
 end;
end;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    Writeln(GetCPUSpeed);
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

编辑

将上面的代码 sn-p 重写为可编译的示例。此示例已在 XE7 中验证,可在 32 位和 64 位环境下运行(启用 UAC)

【讨论】:

  • 这需要管理员权限。
  • @DoctorLai:不,你没有,每个人都对这些密钥拥有 READ 权限。如果您不相信我,请检查 regedit...
  • 对于 32 位是的,你是对的,但是在 XE8 64 位下编译相同的代码,你需要管理员才能获得正确的值,否则它将返回空字符串。刚刚试过。
  • 检查我的答案。我昨天遇到了这个问题,因此将 32 位程序集重写为 64 位代码。效果很好。
  • @DoctorLai,注册表读取适用于为 64 位平台编译的 W7 64 位。只需拨打Reg.OpenKey('HARDWARE\DESCRIPTION\System\CentralProcessor\0',FALSE) 即可。
【解决方案2】:

我认为您可以使用 WMI 访问此信息。

GLibWMI 组件可以在这个网站 (http://neftali.clubdelphi.com) 或 sourceforge (http://sourceforge.net/projects/glibwmi/) 上找到。 当前版本是 1.8b,并且有一个名为 TProcessorInfo 的组件,您可以通过它获取此信息。

它具有 (CurrentclockSpeedMaxClockSpeed) 等属性。

库附带的一个示例是关于这个类 (TProcessorInfo)。

源代码可用,因此您可以根据需要扩展它以访问其他 WMI 类。

如果您不想使用组件,可以使用Rodrigo Ruz 创建的工具"WMI Delphi code Creator" 获取所需的代码来获取此属性。

问候。

【讨论】:

    【解决方案3】:

    注册表不是一个好的解决方案,因为它可能会被更改并且可能需要用户许可(读取注册表)。

    以下代码可以在 32 位和 64 位的 Delphi XE-8 下编译,遵循 SAME 原则,因此这应该在 32 位和 64 位中为您提供一致的值。

    {$IFDEF CPUX64}
    function GetCpuClockCycleCount: Int64; assembler; register;
    asm
        dw 310Fh // rdtsc
        shl rdx, 32
        or rax, rdx
    end;
    {$ENDIF}
    
    function GetCPUSpeed: double;
    {$IFDEF CPUX86}
    const
      DelayTime = 500; // measure time in ms
    var
      TimerHi, TimerLo: DWOrd;
      PriorityClass, 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;
    {$ELSE}
    const
      DelayTime = 500;
    var
      x, y: UInt64;
      PriorityClass, Priority: Integer;
    begin
      PriorityClass := GetPriorityClass(GetCurrentProcess);
      Priority      := GetThreadPriority(GetCurrentThread);
      SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
      SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
      Sleep(10);
      x := GetCpuClockCycleCount;
      Sleep(DelayTime);
      y := GetCpuClockCycleCount;
      SetThreadPriority(GetCurrentThread, Priority);
      SetPriorityClass(GetCurrentProcess, PriorityClass);
      Result := ((y - x) and $FFFFFFFF) / (1000 * DelayTime);
    end;
    {$ENDIF}
    

    【讨论】:

      【解决方案4】:

      从技术上讲,您 CPU 中的每个内核都可以以不同的频率运行,您可以使用此 WMI 示例来获取每个“内核”的频率,尽管它计算的是逻辑内核而不是物理内核。

      这是一个 VCL 示例

      uses : ComObj,ActiveX;
      
      procedure  GetProcessorPerformanceInfo;
      const
        WbemUser            ='';
        WbemPassword        ='';
        WbemComputer        ='localhost';
        wbemFlagForwardOnly = $00000020;
      var
        FSWbemLocator : OLEVariant;
        FWMIService   : OLEVariant;
        FWbemObjectSet: OLEVariant;
        FWbemObject   : OLEVariant;
        oEnum         : IEnumvariant;
        iValue        : LongWord;
      begin;
        Form5.ListBox1.Clear;
        Form5.Tfreq.Clear;
        Form5.Tusage.Clear;
        FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
        FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\WMI', WbemUser, WbemPassword);
        FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM ProcessorPerformance','WQL',wbemFlagForwardOnly);
        oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
        while oEnum.Next(1, FWbemObject, iValue) = 0 do
        begin
          Form5.ListBox1.Items.Add(Format('frequency   %d',[Integer(FWbemObject.frequency)])+Format('%s',[String(FWbemObject.InstanceName)]));// Uint32
          FWbemObject:=Unassigned;
        end;
      end;  
      

      您可以使用一个非常好的工具来创建这些,这是使用来自https://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/ 的 Delphi WMI 代码生成器制作的

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2023-03-22
        • 1970-01-01
        • 2011-12-25
        相关资源
        最近更新 更多