草庐IT

c# - 在获得 CPU 频率方面需要一些帮助

coder 2024-02-09 原文

我正在尝试制作一个 C# 软件来读取有关 CPU 的信息并将它们显示给用户(就像 CPU-Z)。 我目前的问题是我找不到显示 CPU 频率的方法。

起初我尝试使用 Win32_Processor 类 的简单方法。事实证明它非常有效,除非 CPU 超频(或降频)。

然后,我发现我的注册表在 HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0 处包含 CPU 的“标准”时钟(即使已超频)。问题在于,在现代 CPU 中,当 CPU 不需要全功率时,核心倍频会降低,因此 CPU 频率也在变化,但注册表中的值保持不变。

我的下一步是尝试使用 RdTSC 实际计算 CPU 频率。我为此使用了 C++,因为如果该方法有效,我可以将它嵌入到 C# 项目中。我在 http://www.codeproject.com/Articles/7340/Get-the-Processor-Speed-in-two-simple-ways 找到了下一个代码 但问题是一样的:程序只给了我最大频率(就像在注册表值中,1-2 Mhz 的差异)而且它看起来也比它应该加载的 CPU 多(我什至有 CPU 负载峰值)。

#include "stdafx.h"
#include <windows.h>
#include <cstdlib>
#include "intrin.h"
#include <WinError.h>
#include <winnt.h>

float ProcSpeedCalc() {

#define RdTSC __asm _emit 0x0f __asm _emit 0x31

    // variables for the clock-cycles:
    __int64 cyclesStart = 0, cyclesStop = 0;
    // variables for the High-Res Preformance Counter:
    unsigned __int64 nCtr = 0, nFreq = 0, nCtrStop = 0;

    // retrieve performance-counter frequency per second:
    if(!QueryPerformanceFrequency((LARGE_INTEGER *) &nFreq))
        return 0;

    // retrieve the current value of the performance counter:
    QueryPerformanceCounter((LARGE_INTEGER *) &nCtrStop);

    // add the frequency to the counter-value:
    nCtrStop += nFreq;


    _asm
    {// retrieve the clock-cycles for the start value:
        RdTSC
        mov DWORD PTR cyclesStart, eax
        mov DWORD PTR [cyclesStart + 4], edx
    }

    do{
    // retrieve the value of the performance counter
    // until 1 sec has gone by:
         QueryPerformanceCounter((LARGE_INTEGER *) &nCtr);
      }while (nCtr < nCtrStop);

    _asm
    {// retrieve again the clock-cycles after 1 sec. has gone by:
        RdTSC
        mov DWORD PTR cyclesStop, eax
        mov DWORD PTR [cyclesStop + 4], edx
    }

    // stop-start is speed in Hz divided by 1,000,000 is speed in MHz
    return    ((float)cyclesStop-(float)cyclesStart) / 1000000;
}


int _tmain(int argc, _TCHAR* argv[])
{

    while(true)
    {
        printf("CPU frequency = %f\n",ProcSpeedCalc());
        Sleep(1000);
    }

    return 0;
}

我还应该提到,我已经在 AMD CPU 上测试了最后一种方法。 我还为 RdTSC 方法尝试了一些其他代码,但没有一个能正常工作。

最后,我试图理解用于制作此程序的代码 https://code.google.com/p/open-hardware-monitor/source/browse/ ,但这对我来说太复杂了。

所以,我的问题是:如何使用 C++ 或 C# 实时确定 CPU 频率(即使在 CPU 超频时)?我知道这个问题被问了很多次,但实际上没有人回答我的问题。

最佳答案

是的,该代码会等待整整一秒钟,这会导致该核心 100% 忙一秒钟。一秒钟的时间足以让动态时钟算法检测负载并将 CPU 频率从节能状态中踢出。如果具有升压功能的处理器实际显示的频率高于标记频率,我不会感到惊讶。

不过,这个概念还不错。您需要做的是 sleep 大约一秒钟的时间间隔。然后,不是假设 RDTSC 调用恰好相隔一秒,而是除以 QueryPerformanceCounter 指示的实际时间。

此外,我建议在调用 QueryPerformanceCounter 之前和之后检查 RDTSC,以检测 RDTSCQueryPerformanceCounter 这会弄乱你的结果。


不幸的是,新处理器上的 RDTSC 实际上并不计算 CPU 时钟周期。因此,这并不反射(reflect)动态变化的 CPU 时钟速率(不过,它确实在没有忙等待的情况下测量标称速率,因此它是对问题中提供的代码的重大改进)。

所以看起来您毕竟需要访问特定于模型的寄存器。哪个can't be done from user-mode . The OpenHardwareMonitor project有一个可以使用的驱动程序和code for the frequency calculations


float ProcSpeedCalc()
{
    /*
        RdTSC:
          It's the Pentium instruction "ReaD Time Stamp Counter". It measures the
          number of clock cycles that have passed since the processor was reset, as a
          64-bit number. That's what the <CODE>_emit</CODE> lines do.
    */
    // Microsoft inline assembler knows the rdtsc instruction.  No need for emit.

    // variables for the CPU cycle counter (unknown rate):
    __int64 tscBefore, tscAfter, tscCheck;
    // variables for the Performance Counter 9steady known rate):
    LARGE_INTEGER hpetFreq, hpetBefore, hpetAfter;


    // retrieve performance-counter frequency per second:
    if (!QueryPerformanceFrequency(&hpetFreq)) return 0;

    int retryLimit = 10;    
    do {
        // read CPU cycle count
        _asm
        {
            rdtsc
            mov DWORD PTR tscBefore, eax
            mov DWORD PTR [tscBefore + 4], edx
        }

        // retrieve the current value of the performance counter:
        QueryPerformanceCounter(&hpetBefore);

        // read CPU cycle count again, to detect context switch
        _asm
        {
            rdtsc
            mov DWORD PTR tscCheck, eax
            mov DWORD PTR [tscCheck + 4], edx
        }
    } while ((tscCheck - tscBefore) > 800 && (--retryLimit) > 0);

    Sleep(1000);

    do {
        // read CPU cycle count
        _asm
        {
            rdtsc
            mov DWORD PTR tscAfter, eax
            mov DWORD PTR [tscAfter + 4], edx
        }

        // retrieve the current value of the performance counter:
        QueryPerformanceCounter(&hpetAfter);

        // read CPU cycle count again, to detect context switch
        _asm
        {
            rdtsc
            mov DWORD PTR tscCheck, eax
            mov DWORD PTR [tscCheck + 4], edx
        }
    } while ((tscCheck - tscAfter) > 800 && (--retryLimit) > 0);

    // stop-start is speed in Hz divided by 1,000,000 is speed in MHz
    return (double)(tscAfter - tscBefore) / (double)(hpetAfter.QuadPart - hpetBefore.QuadPart) * (double)hpetFreq.QuadPart / 1.0e6;
}

大多数编译器都提供了一个 __rdtsc() 内在函数,在这种情况下,您可以使用 tscBefore = __rdtsc(); 而不是 __asm block .不幸的是,这两种方法都是特定于平台和编译器的。

关于c# - 在获得 CPU 频率方面需要一些帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17774118/

有关c# - 在获得 CPU 频率方面需要一些帮助的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  3. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  4. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  5. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  8. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  9. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  10. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

随机推荐