• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Creative Commons License
            本Blog采用 知識(shí)共享署名-非商業(yè)性使用-禁止演繹 3.0 Unported許可協(xié)議 進(jìn)行許可。 —— Fox <游戲人生>

            游戲人生

            游戲人生 != ( 人生 == 游戲 )
            站點(diǎn)遷移至:http://www.yulefox.com。請(qǐng)訂閱本博的朋友將RSS修改為http://feeds.feedburner.com/yulefox
            posts - 62, comments - 508, trackbacks - 0, articles - 7

            Author: Fox

            前兩天在買《計(jì)算機(jī)程序設(shè)計(jì)藝術(shù)》中文版的時(shí)候,偶然發(fā)現(xiàn)《編程之美》這本書(shū),當(dāng)時(shí)翻了一下,看到“讓CPU占用率曲線聽(tīng)你指揮”這樣的題目確實(shí)讓人為之一動(dòng)。寫一段代碼,可以讓CPU占有率曲線畫(huà)出平滑的正弦曲線,有點(diǎn)意思:-)。

            當(dāng)然,最后沒(méi)有買這本書(shū),雖然我可以肯定這是本好書(shū)。

            我從CSDN讀書(shū)上找到幾節(jié),閑來(lái)讀一讀。今天來(lái)討論一下《讓CPU占用率曲線聽(tīng)你指揮》。

            題目:寫一個(gè)程序,讓用戶來(lái)決定Windows任務(wù)管理器(Task Manager)的CPU占用率。程序越精簡(jiǎn)越好,計(jì)算機(jī)語(yǔ)言不限。例如,可以實(shí)現(xiàn)下面三種情況:

            1.    CPU的占用率固定在50%,為一條直線;

            2.    CPU的占用率為一條直線,但是具體占用率由命令行參數(shù)決定(參數(shù)范圍1~ 100);

            3.    CPU的占用率狀態(tài)是一個(gè)正弦曲線。

            在討論具體實(shí)現(xiàn)之前,一個(gè)非常重要的問(wèn)題是:什么是CPU占用率?

            編程之美》寫道:“在任務(wù)管理器的一個(gè)刷新周期內(nèi),CPU忙(執(zhí)行應(yīng)用程序)的時(shí)間和刷新周期總時(shí)間的比率,就是CPU的占用率,也就是說(shuō),任務(wù)管理器中顯示的是每個(gè)刷新周期內(nèi)CPU占用率的統(tǒng)計(jì)平均值。

            打開(kāi)“Windows 任務(wù)管理器”,“性能”中有“CPU使用記錄”一項(xiàng),給出的就是CPU占有率曲線。

            至于一個(gè)刷新周期到底是多長(zhǎng),書(shū)中似乎沒(méi)有明確給出,只是說(shuō)“大約是1秒鐘更新一次”,我打開(kāi)Windows自帶的時(shí)鐘,也感覺(jué)大約是1秒鐘。

            另外的常識(shí)是:

            單核環(huán)境下,空死循環(huán)會(huì)導(dǎo)致100%的CPU占有率。雙核環(huán)境下,CPU總占有率大約為50%,四核會(huì)不會(huì)是25%左右呢?(我沒(méi)有四核,只能猜測(cè)了,估計(jì)各核間切換也會(huì)耗掉點(diǎn)時(shí)間,因?yàn)槲业碾p核環(huán)境并沒(méi)有出現(xiàn)一核100%,另一核空閑的情況)。

            當(dāng)CPU整個(gè)刷新周期(絕大多數(shù)時(shí)間)空閑時(shí),CPU占有率趨于0。

            書(shū)中給出的正弦實(shí)現(xiàn)如下:

            1 #include "Windows.h"
            2 #include "stdlib.h"
            3 #include "math.h" 
            4 
            5 const double SPLIT = 0.01;
            6 const int COUNT = 200;
            7 const double PI = 3.14159265;
            8 const int INTERVAL = 300;
            9 
            10 int _tmain(int argc, _TCHAR* argv[])
            11 {
            12     DWORD busySpan[COUNT];  //array of busy times
            13     DWORD idleSpan[COUNT];  //array of idle times
            14     int half = INTERVAL / 2;
            15     double radian = 0.0;
            16     for(int i = 0; i < COUNT; i++)
            17     {
            18         busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));
            19         idleSpan[i] = INTERVAL - busySpan[i];
            20         radian += SPLIT;
            21     }
            22     DWORD startTime = 0;
            23     int j = 0;
            24     while (true)
            25     {
            26         j = j % COUNT;
            27         startTime = GetTickCount();
            28         while ((GetTickCount() - startTime) <= busySpan[j]) ;
            29         Sleep(idleSpan[j]);
            30         j++;
            31     }
            32     return 0;
            33 }


            在單核環(huán)境(P4 2.40)下,其表現(xiàn)還是不錯(cuò)的:

            點(diǎn)擊查看大圖

            在雙核環(huán)境(Core2 E4500)下,就有點(diǎn)差強(qiáng)人意不盡人意了:

            點(diǎn)擊查看大圖

            不過(guò),總還能看出是正弦曲線。

            上面兩圖的問(wèn)題:

            1) 單核時(shí)曲線不夠平滑,是由于QQ等程序占用CPU所致;

            2) 雙核時(shí)曲線更加抖動(dòng),我的理解是除其他程序影響外,由于線程沒(méi)有固定運(yùn)行在一個(gè)CPU上導(dǎo)致的,后面看到書(shū)上提到線程遷移,個(gè)人感覺(jué)這個(gè)叫法欠妥啊,總覺(jué)得線程遷移令人費(fèi)解。

            可以立即想到的是:讓進(jìn)程在指定處理器上運(yùn)行(處理器親緣關(guān)系),由Windows提供了兩個(gè)API可以做到這一點(diǎn):GetCurrentProcessSetProcessAffinityMask的。

            修改之后的代碼如下:

            1 #include "Windows.h"
            2 #include "stdlib.h"
            3 #include "math.h" 
            4 
            5 const double SPLIT = 0.01;
            6 const int COUNT = 200;
            7 const double PI = 3.14159265;
            8 const int INTERVAL = 300;
            9 
            10 int _tmain(int argc, _TCHAR* argv[])
            11 {
            12    SetProcessAffinityMask(
            13         GetCurrentProcess(),
            14         0x00000001          //cpu mask
            15         );
            16 
            17     DWORD busySpan[COUNT];  //array of busy times
            18     DWORD idleSpan[COUNT];  //array of idle times
            19     int half = INTERVAL / 2;
            20     double radian = 0.0;
            21     for(int i = 0; i < COUNT; i++)
            22     {
            23         busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));
            24         idleSpan[i] = INTERVAL - busySpan[i];
            25         radian += SPLIT;
            26     }
            27     DWORD startTime = 0;
            28     int j = 0;
            29     while (true)
            30     {
            31         j = j % COUNT;
            32         startTime = GetTickCount();
            33         while ((GetTickCount() - startTime) <= busySpan[j]) ;
            34         Sleep(idleSpan[j]);
            35         j++;
            36     }
            37     return 0;
            38 }


            雙核環(huán)境(Core2 E4500)修改之后的輸出如下:

            點(diǎn)擊查看大圖

            我理想中的表現(xiàn)是:

            1) 曲線是平滑的,最好不因其他應(yīng)用程序或操作的執(zhí)行而改變;

            2) 不管是單核還是雙核,峰值皆為100%,谷值為0。

            對(duì)于第一點(diǎn),其實(shí)就是保證任一刷新周期中的CPU占有率都可以被精確控制在0-100之間,如果你可以使CPU一直保持50%(而不是近似的上下波動(dòng)),產(chǎn)生一條平滑的曲線就很easy了。

            問(wèn)題的關(guān)鍵在于,除了當(dāng)前你寫的程序可以控制,其他程序或操作如何控制?或者說(shuō):如何控制CPU的運(yùn)行情況才是關(guān)鍵之處。

            PS: 一晚上老是斷網(wǎng),搞得思路頻頻被打斷,興致也損了大半??傊?a target="_blank">編程之美》還是值得玩味一把吧:D。

            Feedback

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-17 12:17 by brent
            俺也看到這章了,

            看到題目的第一反應(yīng)是設(shè)計(jì)一個(gè)反饋系統(tǒng)。

            看到解答挺失望的,感覺(jué)有點(diǎn)雕蟲(chóng)小技的味道

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-17 21:02 by Fox
            恩,MS的面試題多如此類,翻一翻還是開(kāi)闊思路

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-18 17:15 by Wang Feng
            unix上怎么辦?

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-18 18:29 by Fox
            @Wang Feng
            呵呵,MS的面試題啊:D

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-20 23:58 by greatws
            呵呵,不錯(cuò)。
            不過(guò)我想到的是直接Hook任務(wù)管理器或者Hook查CPU利用率的API,可能會(huì)更精確

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-04-22 00:38 by www
            > 除了當(dāng)前你寫的程序可以控制,其他程序或操作如何控制?

            書(shū)上也談到了一些。不過(guò)不是控制,而是“適應(yīng)”。

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2008-06-28 00:40 by 不死阿三
            試過(guò)了,用c#改寫了一下,總是感覺(jué)不是很平滑。

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2009-03-29 01:00 by kg
            樓主,能不能解釋下,為什么要這樣設(shè)定:
            busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));
            idleSpan[i] = INTERVAL - busySpan[i];

            為什么不可以這樣:
            busySpan[i] = (DWORD)(1 /2 + (sin(PI * radian) * 1 / 2));
            idleSpan[i] = 1- busySpan[i];
            這樣是不是CPU使用率=1/2*(1+sin(PI * radian))?

            liwenge21@sina.com,謝謝回復(fù)。

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2010-12-26 16:55 by lateCpp
            28 while ((GetTickCount() - startTime) <= busySpan[j]) ;
            29 Sleep(idleSpan[j]);

            ========================
            這個(gè)可以控制到sleep是正弦曲線嗎?
            我對(duì)WINDOWS API不太熟,大致理解是這樣:

            如果j=0時(shí),busySpan[0]=150,相應(yīng)的,IdleSpan[0]=150;
            如果j等某值時(shí),busySpan[j]=180,相應(yīng)的,IdleSpan[j]=120。(由計(jì)算公式,busySpan=150*(1+sin(j*pi)),可知,可以取到這個(gè)值,起碼近似。)

            這時(shí)候來(lái)看while循環(huán)(上面所引的行28):
            第一次循環(huán):滿足<=180條件,執(zhí)行一次Sleep(120);
            第二次循環(huán):依然滿足<=180的條件 ,再執(zhí)行一次Sleep(120);
            第三次循環(huán):不滿足,跳出;
            這樣一共Sleep了240秒,顯然,這跟原來(lái)Sleep(IdleSpan[j])的初衷是不一致的。這個(gè)對(duì)產(chǎn)生的曲線應(yīng)該也有影響吧?

            不知道理解的對(duì)不。希望交流討論。xueyayang AT gmail DOT com

            # re: 編程之美:讓CPU占用率曲線聽(tīng)你指揮  回復(fù)  更多評(píng)論   

            2011-01-27 14:08 by BopGroup
            《編程之美》這在計(jì)劃修訂改版,歡迎大家提建議,這里(http://bop1.wikispaces.com/)有包含所有題目的wiki,大家可以注冊(cè)后提問(wèn),也可以直接給我發(fā)郵件 lispython@gmail.com。
            久久ww精品w免费人成| 狼狼综合久久久久综合网| 国产精品久久久久久久| 女同久久| 精品久久久久久无码中文字幕| 三级片免费观看久久| 国产L精品国产亚洲区久久| 久久久久久久久久久久中文字幕 | 无码精品久久一区二区三区| 狠狠色丁香婷婷久久综合五月 | 狠色狠色狠狠色综合久久| 精品久久久久久久久免费影院| 久久国产乱子精品免费女| 久久精品青青草原伊人| 亚洲国产精品成人AV无码久久综合影院 | 亚洲国产成人精品91久久久| 精品国产青草久久久久福利| 性高湖久久久久久久久| 久久综合给久久狠狠97色| 精品久久久久久国产91| 狠狠色噜噜狠狠狠狠狠色综合久久| 国内精品伊人久久久久| 久久精品国产亚洲5555| 一本久久a久久精品综合香蕉| 国内高清久久久久久| 丰满少妇人妻久久久久久4| 亚洲精品国精品久久99热| 欧美熟妇另类久久久久久不卡| 久久综合丁香激情久久| 久久久久久免费视频| 精品久久久久久久久久中文字幕 | 狠狠综合久久AV一区二区三区 | 久久综合久久自在自线精品自 | 99久久99这里只有免费费精品| 久久人人超碰精品CAOPOREN| 久久久久久精品免费看SSS| 色偷偷888欧美精品久久久| 91精品国产色综合久久| 色天使久久综合网天天| 一级做a爰片久久毛片毛片| 久久精品这里只有精99品|