• <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>

            雁過無痕

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::



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

             

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

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

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

             

            控制CPU占用率,不僅僅是出于好玩而已。以前的某些程序,特別是某些老游戲,在新的機器上運行速度太快,必須先給CPU降速,才能順利運行那些程序,有個共享軟件CPUKiller,就是專門弄這個的。

             

            控制CPU占用率,因為要調(diào)用WindowsAPI,要考慮到多核、超線程的情況,要考慮到不同版本的Windows的計時相關(guān)的API的精度不同,使問題變得相當(dāng)復(fù)雜,若再考慮其它程序的CPU占用率,則該問題則變得很煩人。(taskmgr調(diào)用了一個未公開的API)

             

            CPU核數(shù)的判斷,書上是調(diào)用GetProcessorInfo,其實可以直接調(diào)用GetSystemInfoSYSTEM_INFO結(jié)構(gòu)的dwNumberOfProcessors成員就是核數(shù)。不知道超線程對這兩種方法有什么影響。

             

            如果不考慮其它程序的CPU占用情況,可以在每個核上開一個線程,運行指定的函數(shù),實現(xiàn)每個核的CPU占用率相同。

             

            要讓CPU的占用率,呈函數(shù) y = calc(t) (0 <= y <= 1, t為時間,單位為ms )分布,只要取間隔很短的一系列點,認(rèn)為在某個間隔內(nèi),y值近似不變。

            設(shè)間隔值為GAP,顯然在指定t值附近的GAP這段時間內(nèi),

            CPU占用時間為:busy = GAP * calc(t)

            CPU空閑時間為:idle = GAP – busy

            因此,很容易寫出下面這個通用函數(shù):

             

             

            void solve(Func *calc)
            {
              
            double tb = 0;
              
            while(1{
                unsigned ta 
            = get_time();
                
            double r = calc(tb);
                
            if (r < 0 || r > 1) r = 1;
                DWORD busy 
            = r * GAP;
                
            while(get_time() - ta < busy) {}
                Sleep(GAP 
            - busy);
                tb 
            += GAP;
              }

            }


            如果CPU占用率曲線不是周期性變化,就要對每個t值都要計算一次,否則,可以只計算第一個周期內(nèi)的各個t值,其它周期的直接取緩存計算結(jié)果。

             

            CPU占用率為正弦曲線為例,顯然:y = 0.5 * (1 + sin(a * t + b))

            其周期T = 2 * PI / a  (PI = 3.1415927),可以指定T值為60s60000ms,則

             可以確定a值為 2 * PI / T, 若在這60000ms內(nèi)我們計算200次(c = 200),則GAP值為 T / c = 300ms.也就是說,只要確定了周期和計算次數(shù),其它幾個參數(shù)也都確定下來。

             

             

            完整代碼如下:

             

            #include<windows.h>
            #include
            <cstdio>
            #include
            <cmath>

            const int PERIOD = 60 * 1000//60,000 ms
            const int COUNT = 200;

            const double PI = 3.1415926535898;
            const double GAP = (double)PERIOD / COUNT;
            const double FACTOR = 2 * PI / PERIOD;  

            typedef 
            double Func(double); 
            inline DWORD get_time() 
            return GetTickCount(); }

            double calc2(double x) {  return (1 + sin(FACTOR * x)) / 2;}

            double calc3(double)
            {
              
            static double cache[COUNT];
              
            static int count = 0;
              
            static bool first = true;
              
            if (first) {
                
            double x = 0.0;
                
            for (int i = 0; i < COUNT; ++i, x += GAP) 
                  cache[i] 
            = (1.0 + sin(FACTOR * x)) / 2.0
                first 
            = false;
              }

              
            if (count >= COUNT) count = 0;
              
            return cache[count++];  
            }


            double calc4(doublereturn 0.8;}

            void solve(Func *calc)
            {
              
            double tb = 0;
              
            while(1{
                unsigned ta 
            = get_time();
                
            double r = calc(tb);
                
            if (r < 0 || r > 1) r = 1;
                DWORD busy 
            = r * GAP;
                
            while(get_time() - ta < busy) {}
                Sleep(GAP 
            - busy);
                tb 
            += GAP;
              }

            }



            void run()
            {
              Func 
            *func[] = { calc2, calc3, calc4 };
              Func 
            *calc = func[1];
              
            const int MAX_CPUS = 32;
              HANDLE handle[MAX_CPUS];
              DWORD thread_id[MAX_CPUS];
              SYSTEM_INFO info;
              GetSystemInfo(
            &info);
              
            const int num = info.dwNumberOfProcessors;
              
            for (int i = 0; i < num; ++i) {
                
            if ( (handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
                     (VOID
            *)calc, 0&thread_id[i])) != NULL) 
                  SetThreadAffinityMask(handle[i], i 
            + 1);
              }

              WaitForSingleObject(handle[
            0],INFINITE);   
            }



            int main()
            {
              run();
            }



            稍微優(yōu)化下:

            #include<cstdio>
            #include
            <cmath>
            #include
            <windows.h>

            const int PERIOD = 60 * 1000//60,000 ms
            const int COUNT = 300;

            const double GAP_LINEAR = 100

            const double PI = 3.1415926535898;
            const double GAP = (double)PERIOD / COUNT;
            const double FACTOR = 2 * PI / PERIOD;  


            typedef 
            double Func(double); 
            inline DWORD get_time() 
            return GetTickCount(); }

            double calc_sin(double x) {  return (1 + sin(FACTOR * x)) / 2;}

            static double Ratio = 0.7;

            void set_ratio()
            {
              
            double ret = 0.0;
              printf(
            "Ratio:([0,1]) ");
              scanf(
            "%lf"&ret);
              
            if (ret < 0.0 || ret > 1.0) ret = 0.5;
              Ratio 
            = ret;
            }


            void solve_nonperiod(Func *calc)
            {
              
            double tb = 0;
              
            while(1{
                unsigned ta 
            = get_time();
                
            double r = calc(tb);
                
            if (r < 0 || r > 1) r = 1;
                DWORD busy 
            = r * GAP;
                
            while(get_time() - ta < busy) {}
                Sleep(GAP 
            - busy);
                
            //tb += GAP;
                tb += get_time() - ta;
              }

            }


            void solve_period(Func *calc)
            {
              
            double x = 0.0;
              
            double cache[COUNT];
              
            for (int i = 0; i < COUNT; ++i, x += GAP) 
                cache[i] 
            = calc(x); 
              
            int count = 0;
              
            while(1{
                unsigned ta 
            = get_time();
                
            if (count >= COUNT) count = 0;
                
            double r = cache[count++];
                DWORD busy 
            = r * GAP;
                
            while(get_time() - ta < busy) {}
                Sleep(GAP 
            - busy);
              }

            }


            void solve_linear(Func*)
            {
              
            const unsigned BUSY =  Ratio * GAP_LINEAR;
              
            const unsigned IDLE = (1 - Ratio) * GAP_LINEAR;
              
            while(1{
                unsigned ta 
            = get_time();
                
            while(get_time() - ta < BUSY) {}
                Sleep(IDLE);
              }

            }



            void run(unsigned index = 0double ratio = -1.0)
            {
              typedef 
            void Solve(Func *calc);
              Func 
            *func[] = { calc_sin};
              Func 
            *calc = func[0];
              Solve 
            *solve_func[] = { solve_linear, solve_period, solve_nonperiod };
              
            if (index >= sizeof(solve_func) / sizeof(solve_func[0])) index = 0;
              Solve 
            *solve = solve_func[index];
              
            if (solve == solve_linear) {
                
            if (ratio >= 0 && ratio <= 1) Ratio = ratio;
                
            else set_ratio();
              }
                
              
            const int MAX_CPUS = 32;
              HANDLE handle[MAX_CPUS];
              DWORD thread_id[MAX_CPUS];
              SYSTEM_INFO info;
              GetSystemInfo(
            &info);
              
            const int num = info.dwNumberOfProcessors;
              
            for (int i = 0; i < num; ++i) {
                
            if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve, 
                                                (VOID
            *)calc, 0&thread_id[i])) != NULL) 
                  SetThreadAffinityMask(handle[i], i 
            + 1);
              }

              WaitForSingleObject(handle[
            0],INFINITE);   
            }



            int main()
            {
              run(
            00.5);
              
            //run(0);
              
            //run(1);
              
            //run(1);
            }


            posted on 2010-12-02 23:19 flyinghearts 閱讀(4683) 評論(2)  編輯 收藏 引用 所屬分類: 編程之美

            評論

            # re: 《編程之美》讀書筆記23: 1.1 讓CPU占用率曲線聽你指揮 2012-07-15 19:56 霧非霧
            如何才能讓CPU的曲線 為 I LOVE YOU這樣的字符啊?  回復(fù)  更多評論
              

            # re: 《編程之美》讀書筆記23: 1.1 讓CPU占用率曲線聽你指揮 2014-10-16 14:48 3d
            const int MAX_CPUS = 32;
            HANDLE handle[MAX_CPUS];
            DWORD thread_id[MAX_CPUS];
            SYSTEM_INFO info;
            GetSystemInfo(&inf  回復(fù)  更多評論
              

            国产一级持黄大片99久久| 亚洲欧美一级久久精品| 亚洲国产精品一区二区久久| 国产精品va久久久久久久| 亚洲国产高清精品线久久| …久久精品99久久香蕉国产| 久久久久亚洲av成人无码电影 | 亚洲国产精品久久电影欧美| 少妇久久久久久被弄高潮| 狠狠色丁香婷婷综合久久来来去| 亚洲精品乱码久久久久久不卡| 久久久久久国产精品免费无码 | 久久婷婷五月综合色高清| 久久久久国产亚洲AV麻豆| 国产婷婷成人久久Av免费高清| 久久影视国产亚洲| 999久久久免费国产精品播放| 97精品伊人久久久大香线蕉 | 九九久久99综合一区二区| 久久综合给合久久狠狠狠97色69| 久久久99精品一区二区| 精品国产福利久久久| 日本久久久久亚洲中字幕| 久久天天躁夜夜躁狠狠| 亚洲国产成人乱码精品女人久久久不卡 | 久久久网中文字幕| 久久精品国产99久久丝袜| 亚洲国产成人久久综合一| 久久精品国产亚洲av麻豆小说| 中文字幕乱码久久午夜| 久久久久久国产精品美女 | 波多野结衣中文字幕久久| 亚洲国产另类久久久精品黑人| 久久精品国产亚洲AV香蕉| 久久精品国产久精国产果冻传媒| 久久无码中文字幕东京热| 久久人人爽人人爽人人爽 | 午夜欧美精品久久久久久久| 久久精品日日躁夜夜躁欧美| 国产成人精品三上悠亚久久| 人人妻久久人人澡人人爽人人精品|