诸如CPUz之类的程序非常擅长于提供有关系统的深度信息(总线速度,内存时序等)。

但是,有一种编程方式可以计算每个内核(和每个处理器,在每个CPU具有多个内核的多处理器系统中),而无需处理特定于CPU的信息。

我正在尝试开发一个防作弊工具(用于时钟受限的基准测试比赛),该工具将能够在基准运行期间记录系统中所有 Activity 内核(在所有处理器上)的CPU时钟。

最佳答案

我将在这里扩展我的评论。对于我来说,这太大了又太深入了,无法放入评论中。

您要执行的操作非常困难-出于以下原因而变得不切实际:

  • 没有获取处理器频率的便携式方法。 rdtsc不会而不是会始终给出正确的频率,这是由于诸如SpeedStep和Turbo Boost之类的影响。
  • 所有已知的测量频率的方法都需要精确地测量时间。但是,坚定的作弊者会篡改系统中的所有时钟和计时器。
  • 以防篡改的方式准确读取处理器频率和时间将需要内核级访问。这意味着Windows的驱动程序签名。


  • 没有获得处理器频率的便携式方法:

    获得CPU频率的“简便”方法是两次调用 rdtsc ,两次调用之间的时间间隔固定。然后将差异除以频率。

    问题在于rdtsc没有给出处理器的真实频率。由于游戏等实时应用程序都依赖它,因此rdtsc需要通过CPU节流和Turbo Boost保持一致。因此,一旦您的系统启动,rdtsc将始终以相同的速率运行(除非您开始使用SetFSB或诸如此类来破坏总线速度)。

    例如,在我的Core i7 2600K上,rdtsc将始终在3.4 GHz上显示频率。但实际上,它通过1.6 GHz的超频Turbo Boost乘法器在4.6 GHz处空闲,并在负载下达到46x时钟。

    但是,一旦找到测量真实频率的方法(或者您对rdtsc感到满意),就可以使用thread-affinities轻松获得每个内核的频率。

    获得真实频率:

    为了获得处理器的真实频率,您需要访问MSR(特定于模型的寄存器)或硬件性能计数器。

    这些是内核级指令,因此需要使用驱动程序。如果您出于分发目的在Windows中尝试此操作,则需要通过正确的驱动程序签名协议(protocol)。此外,代码因处理器品牌和型号而异,因此每一代处理器都需要不同的检测代码。

    进入此阶段后,可以通过多种方式读取频率。

    在Intel处理器上,硬件计数器可让您计算原始CPU周期。结合精确测量实时的方法(下一部分),您可以计算出真实的频率。 MSR使您可以访问其他信息,例如CPU倍频器。

    所有已知的测量频率的方法都需要精确测量时间:

    这也许是更大的问题。您需要一个计时器才能测量频率。有能力的黑客将可以篡改C/C++中可以使用的所有时钟。
    这包括以下所有内容:
  • clock()
  • gettimeofday()
  • QueryPerformanceCounter()
  • 等...

  • list 一直在继续。换句话说,您不能信任任何计时器,因为有能力的黑客将能够欺骗所有计时器。例如,可以通过直接在OS中更改系统时钟来欺骗clock()gettimeofday()。愚弄QueryPerformanceCounter()更加困难。

    真正衡量时间:

    上面列出的所有时钟都容易受到攻击,因为它们通常以某种方式源自同一系统基本时钟。该系统基本时钟通常与系统基本时钟相关联-在系统已经通过超频实用程序启动后可以更改该系统基本时钟。

    因此,获得可靠且防篡改的时间度量的唯一方法是读取外部时钟,例如HPETACPI。不幸的是,这些似乎也需要内核级访问。

    总结:

    建立任何类型的防篡改基准几乎肯定需要编写内核模式驱动程序,该驱动程序需要Windows的证书签名。对于普通的基准作者而言,这通常是太多的负担。

    这导致缺乏防篡改基准,这可能导致了竞争性超频社区近年来的整体下滑。

    关于c++ - 找出CPU时钟频率(每个内核,每个处理器),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8351944/

    10-16 07:23