玩轉CPU之直線

近期在看編程之美,看到第一個問題時,一會兒就被吸引了,原來在windows 的任務管理器中還可以讓CPU舞動起來,再一次的相信了編程中僅僅有想不到沒有作不到,對於書中的作法和網上的實現大體都一樣。只是在看後面的解法以前,個人解法和書中第一種簡單的控制之法一樣,而且我還引入了一個實時監測CPU主頻的函數。可以移植到其它的PC上。ios

#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核心來執行windows

相關文章
相關標籤/搜索