首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >汇编语言CPU测频算法

汇编语言CPU测频算法
EN

Stack Overflow用户
提问于 2008-09-15 17:50:32
回答 10查看 11.5K关注 0票数 17

用来测量处理器频率的常用算法是什么?

EN

回答 10

Stack Overflow用户

发布于 2008-09-15 18:20:47

酷睿双核之后的英特尔CPU支持两个型号特定的寄存器,分别称为IA32_MPERF和IA32_APERF。

MPERF按CPU支持的最大频率计数,而APERF按实际当前频率计数。

实际频率由以下公式给出:

你可以通过这个流程来阅读它们

代码语言:javascript
运行
复制
; read MPERF
mov ecx, 0xe7
rdmsr
mov mperf_var_lo, eax
mov mperf_var_hi, edx

; read APERF
mov ecx, 0xe8
rdmsr
mov aperf_var_lo, eax
mov aperf_var_hi, edx

但请注意,rdmsr是特权指令,并且只能在环0中运行。

我不知道操作系统是否提供了读取这些内容的接口,尽管它们的主要用途是电源管理,因此它可能不提供这样的接口。

票数 18
EN

Stack Overflow用户

发布于 2008-09-23 00:16:39

我将在这个答案中用各种细节来描述自己,但这到底是什么……

几年前,我不得不在基于Windows的个人电脑上解决这个问题,所以我使用的是英特尔x86系列处理器,如486、奔腾等。这种情况下的标准算法是执行一长串DIVide指令,因为这些指令通常是英特尔集中CPU占用最多的单指令。因此,内存预取和其他体系结构问题不会对指令执行时间产生实质性影响--预取队列始终是满的,并且指令本身不会触及任何其他内存。

您可以使用在您运行的环境中可以访问的最高分辨率时钟对其进行计时。(在我的例子中,我在兼容的PC上运行的时间接近启动时间,所以我直接对主板上的计时器芯片进行编程。在真实的操作系统中不推荐这样做,目前通常有一些合适的API可供调用)。

您必须处理的主要问题是不同的CPU类型。当时有英特尔、AMD和一些较小的供应商,如Cyrix制造x86处理器。相对于DIV指令,每个模型都有其自己的性能特征。我的汇编定时函数只会返回一定数量的DIV指令在紧凑循环中占用的时钟周期数。

因此,我所做的是从运行我想要计时的每个处理器型号的实际PC中收集一些计时(该函数的原始返回值),并将这些计时记录在一个电子表格中,对照已知的处理器速度和处理器类型进行记录。我实际上有一个命令行工具,它只是我的计时函数的一个薄薄的外壳,我会把一个磁盘拿到电脑商店里,从显示模型中获得计时!(当时我在一家非常小的公司工作)。

使用这些原始计时,我可以绘制一个理论图,说明对于特定CPU的任何已知速度,我应该获得什么样的计时。

这就是诀窍:我总是讨厌当你运行一个实用程序时,它会宣布你的CPU是99.8 Mhz或其他什么。很明显,它是100兆赫,在测量中只有一个小的舍入误差。在我的电子表格中,我记录了每个处理器供应商销售的实际速度。然后,我将使用实际计时的曲线图来估计任何已知速度的预计计时。但我会沿着这条线建立一个点表,在那里计时应该舍入到下一个速度。

换句话说,如果100个刻度表示500 Mhz,200个刻度表示250 Mhz,那么我将构建一个表格,说明低于150的任何值都是500 Mhz,高于150的任何值都是250 Mhz。(假设这是该芯片供应商提供的唯一两种速度)。这很好,因为即使PC上的一些奇怪的软件打乱了我的计时,最终的结果通常仍然是准确的。

当然,现在,在超频、电源管理的动态时钟速度和其他类似花招的日子里,这样的方案将不太实用。在运行计时函数之前,至少需要做一些事情来确保CPU处于动态选择的最高速度。

好了,我要回去把孩子们赶出我的草坪了。

票数 7
EN

Stack Overflow用户

发布于 2009-06-26 09:06:03

自奔腾以来,在x86英特尔处理器上的一种方法是使用RDTSC指令的两个采样,并具有已知挂壁时间的延迟循环,例如:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>

uint64_t rdtsc(void) {
    uint64_t result;
    __asm__ __volatile__ ("rdtsc" : "=A" (result));
    return result;
}

int main(void) {
    uint64_t ts0, ts1;    
    ts0 = rdtsc();
    sleep(1);
    ts1 = rdtsc();    
    printf("clock frequency = %llu\n", ts1 - ts0);
    return 0;
}

(在32位平台上,与GCC)

如果设置了CR4中的TSC标志,则RDTSC在环3中可用,这是常见的,但不能保证。这种方法的一个缺点是,如果频率缩放发生在延迟内,则它很容易受到影响结果的频率缩放变化的影响。为了缓解这一问题,您可以执行使CPU保持繁忙的代码,并不断轮询系统时间,以查看延迟期是否已到期,从而使CPU处于可用的最高频率状态。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档