首页 > 代码库 > 玩转CPU之直线

玩转CPU之直线

近期在看编程之美,看到第一个问题时,一下子就被吸引了,原来在windows 的任务管理器中还能够让CPU舞动起来,再一次的相信了编程中仅仅有想不到没有做不到,对于书中的做法和网上的实现大致都同样。只是在看后面的解法之前,我的解法和书中第一种简单的控制之法同样,并且我还引入了一个实时监測CPU主频的函数。能够移植到其它的PC上。

#include <windows.h>
#include <iostream>

using namespace std;

int size = 0;

int getCPUFrequency()
{
	static int time[2];              //定义一个整型数组time
	int a = 0;                   //定义整形变量a=0(在后面的运算中用来存商)
	int b = 0;                   //定义整形变量b=0(在后面的运算中用来存余数)

	__asm{ 
		rdtsc                        //RDTSC指令,意思是读取时间标记计数器(Read Time-Stamp Counter)
		mov ecx,offset time            //将time的偏移地址存入ecx
		mov [ecx+0],edx              //把TSC的值的高32位存入[ecx+0]中
		mov [ecx+4],eax              //把TSC的值的低32位存入[ecx+4]中
	}

	Sleep(1000);                  //延时1秒

	__asm{
		rdtsc
		mov ebx,offset time            //将time的偏移地址存入ebx
		sub eax,[ebx+4]               //把延时1秒后的TSC值的高32位减去1秒前的TSC值的高32位
		sbb edx,[ebx+0]               //把延时1秒后的TSC值的低32位减去1秒前的TSC值的低32位
		mov ecx,1000000000
		div ecx                      //将2次TSC差值除以1,000,000,000
		mov a,eax                    //将结果中的商赋值于a
		mov b,edx                   //将结果中的余数赋值于b
	}

    b=b/10000000;                              //取余数中的最高2位

    printf("该机CPU主频是: %d.%dGHz\n",a,b);    //打印结果

	return a*1000+b*10;
}

int main()
{
	size = getCPUFrequency()*2/5*1000000;// 解释第一点
	size -= 100000;//解释第二点
	while(1)
	{
		for(int i=0; i < size; i++)
				;
		Sleep(10);//解释第三点
	}
	return 0;
} 

如今来解释第一点:现代CPU每一个时钟周期能够运行两条以上的代码。取平均值就是2。CPU的主频表示1秒运行加法的次数,对于除以5的运算,由于在底层的加法实现中。CPU要进行5次运算才干够进行一次加法运算。

next:
mov eax, dword ptr[i]; 将i 的值放入寄存器
add eax, 1;		寄存器加1
mov dword ptr[i], eax;  寄存器赋值回i
cmp eax, dword ptr[n];  比較i 和 n
jl next;    小于n 则继续运行

解释第二点:上述讨论的情况都是在理想的情况下,就是考虑CPU仅仅执行当前这一个程序。而实际中CPU还会花时间执行其它的程序。所以在执行这个程序时须要将执行的次数适当的降低,至于降低的数量依当前OS的执行进程而定。

解释第三点:至于CPU的睡眠时间。10ms 是接近windows的调度时间片。


如今的电脑非常难看到单核的CPU了所以在程序的执行过程中在windows的任务管理器中的进程模块中找到程序的执行号,点击鼠标右键,设置相关性,将此执行的程序用一个CPU核心来执行


玩转CPU之直线