让CPU占用率曲线听你指挥

由于网上已经有很多有关此问题的博客,本文参考了http://blog.csdn.net/wesweeky/article/details/6402564

题目:写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率。程序越精简越好,计算机语言不限。例如,可以实现下面三种情况:

1.    CPU的占用率固定在50%,为一条直线;

2.    CPU的占用率为一条直线,但是具体占用率由命令行参数决定(参数范围1~ 100);

3.    CPU的占用率状态是一个正弦曲线。

控制的方式其实就是在任务管理器刷新的一个周期内,使得cpu忙的时间控制在一定的比例。

任务管理器的刷新周期是1秒,我的cpu是2.4GHZ,

现代cpu每个时钟周期可执行两条以上的代码,取平均值2,于是

(2400 000 000*2)/5=960000000(循环/秒) 每秒可以执行循环960000000次

不能简单的取n=9600000000然后sleep(1000),如果让cpu工作1s,休息1s很可能是锯齿,先达到一个峰值然后跌入一个很低的占有率;所以我们睡眠时间改为10ms,10ms比较接近windows的调度时间,n=9600000。如果sleep时间选的太小,会造成线程频繁的唤醒和挂起,无形中增加了内核时间的不确定性因此代码如下:

一、单核情况下

    解法一:

  1. #include <windows.h>  
  2.   
  3. int main(void)  
  4. {  
  5.     //50%  
  6.     //Thread 0 can only run on CPU 0.  
  7.     //SetThreadAffinityMask(GetCurrentProcess(), 0x00000001);  //这个是指定在哪个cpu上运行该线程
  8.     while(true)  
  9.     {  
  10.         for(int i=0;i<10120000;i++)  
  11.             ;  
  12.         Sleep(10);  
  13.     }  
  14.     return 0;  
  15.       
  16.   
  17. }  

                 注意:不同型号的机器的差异性,使得该方法有很大的缺陷,比如我的电脑,只能在调节Sleep(30)的时候才能达到勉强的效果如图:

                  

解法二:

解法二:使用GetTickCount()和Sleep()

GetTickCount()可以得到“系统启动到现在”所经历的时间的毫秒值,最多可以统计49.7天,因此我们可以利用GetTickCount()判断busy loop要循环多久,如下:

[cpp]  view plain copy
  1. #include <windows.h>  
  2.   
  3. int main(void)  
  4. {  
  5.           
  6.     //50%  
  7.     int busyTime=10;  
  8.     int idleTime=busyTime;  
  9.     _int64 startTime;  
  10.          //SetThreadAffinityMask(GetCurrentProcess(), 0x00000001);  
  11.     while(true)  
  12.     {  
  13.         startTime=GetTickCount();  
  14.         while((GetTickCount()-startTime)<=busyTime)  
  15.         {  
  16.             ;  
  17.         }  
  18.         Sleep(idleTime);  
  19.     }  
  20.     return 0;  
  21. }  

            注意:该方法有和方法一有同样的缺点,我的机器的busyTime=50,效果如图:

      



上面两种解法都是假设当前系统只有当前程序在运行,但实际上,操作系统有很多程序会同时调试执行各种任务,如果此刻进程使用10%的cpu,那我们的程序只有使用40%的cpu才能达到50%的效果。

Perfmon.exe是从WIN NT开始就包含在windows管理工具中的专业检测工具之一。我们可以用程序来查询Perfmon的值,.Net Framework提供了PerformanceCounter这一对象,可以方便的查询当前各种性能数据,包括cpu使用率,因此解法三如下:

      

解法三:能动态适应的解法

 

[c-sharp]  view plain copy
  1. using System;  
  2. using System.Diagnostics;  
  3. namespace cpu  
  4. {  
  5.     class Program  
  6.     {  
  7.         static void Main(string[] args)  
  8.         {  
  9.            cpu(0.5);  
  10.         }  
  11.         static void cpu(double level)  
  12.         {  
  13.             PerformanceCounter p = new PerformanceCounter("Processor""% Processor Time""_Total");  
  14.             if (p == null)  
  15.             {  
  16.                 return;  
  17.             }  
  18.             while (true)  
  19.             {  
  20.                 if (p.NextValue() > level)  
  21.                     System.Threading.Thread.Sleep(10);  
  22.             }  
  23.         }  
  24.     }  
  25. }  

由于我的实验都是在虚拟机上安装的Qt开发环境的,没有安装VS,所以无法实验该C#代码的实现。

    

解法四:正弦曲线

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

其中busySpan[i]=(DWORD)(half+(sin(PI*radian)*half));
  idleSpan[i]=INTERVAL-busySpan[i];

这样保证了占有率=busy/(busy+idle)=(half+(sin(PI*radian)*half))/(2*half)=(1+sin(PI*radian))/2 在0到100%之间!。

               

下面更深入讨论,http://www.cnblogs.com/flyinghearts/archive/2011/03/22/1991965.html这篇博文很好,讨论了在双核情况下,每个cpu显示不同的曲线。如下:

控制CPU占用率,不仅仅是出于好玩而已。以前的某些程序,特别是某些老游戏,在新的机器上运行速度太快,必须先给CPU降速,才能顺利运行那些程序,有个共享软件CPUKiller,就是专门弄这个的。

控制CPU占用率,因为要调用Windows的API,要考虑到多核、超线程的情况,要考虑到不同版本的Windows的计时相关的API的精度不同,使问题变得相当复杂,若再考虑其它程序的CPU占用率,则该问题则变得很烦人。(taskmgr调用了一个未公开的API)。

对CPU核数的判断,书上是调用GetProcessorInfo,其实可以直接调用GetSystemInfo,SYSTEM_INFO结构的dwNumberOfProcessors成员就是核数。不知道超线程对这两种方法有什么影响。

如果不考虑其它程序的CPU占用情况,可以在每个核上开一个线程,运行指定的函数,实现每个核的CPU占用率相同

要让CPU的占用率,呈函数 y = calc(t) (0 <= y <= 1, t为时间,单位为ms )分布,只要取间隔很短的一系列点,认为在某个间隔内,y值近似不变。

设间隔值为GAP,显然在指定t值附近的GAP这段时间内,

CPU占用时间为:busy = GAP * calc(t),

CPU空闲时间为:idle = GAP - busy

因此,很容易写出下面这个通用函数:

[cpp]  view plain copy
  1. void solve(Func *calc)  
  2. {  
  3.   double tb = 0;  
  4.   while(1)   
  5.  {  
  6.     unsigned ta = get_time();  
  7.     double r = calc(tb);  
  8.     if (r < 0 || r > 1) r = 1;  
  9.     DWORD busy = r * GAP;  
  10.     while(get_time() - ta < busy) {}  
  11.     Sleep(GAP - busy);  
  12.     tb += GAP;  
  13.   }  
  14. }  

 

如果CPU占用率曲线不是周期性变化,就要对每个t值都要计算一次,否则,可以只计算第一个周期内的各个t值,其它周期的直接取缓存计算结果。

以CPU占用率为正弦曲线为例,显然:y = 0.5 * (1 + sin(a * t + b))

其周期T = 2 * PI / a  (PI = 3.1415927),可以指定T值为60s即60000ms,则

 可以确定a值为 2 * PI / T, 若在这60000ms内我们计算200次(c = 200),则GAP值为 T / c = 300ms.也就是说,只要确定了周期和计算次数,其它几个参数也都确定下来。

代码如下

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cmath>  
  3. #include<windows.h>  
  4.   
  5. static int PERIOD = 60 * 1000; //周期ms  
  6. const int COUNT = 300;  //一个周期计算次数  
  7. const double GAP_LINEAR = 100;  //线性函数时间间隔100ms  
  8. const double PI = 3.1415926535898; //PI  
  9. const double GAP = (double)PERIOD / COUNT; //周期函数时间间隔  
  10. const double FACTOR = 2 * PI / PERIOD;  //周期函数的系数  
  11. static double Ratio = 0.5;  //线性函数的值 0.5即50%  
  12. static double Max=0.9; //方波函数的最大值  
  13. static double Min=0.1; //方波函数的最小值  
  14.   
  15. typedef double Func(double);  //定义一个函数类型 Func*为函数指针  
  16. typedef void Solve(Func *calc);//定义函数类型,参数为函数指针Func*  
  17. inline DWORD get_time()   
  18. {   
  19.     return GetTickCount(); //操作系统启动到现在所经过的时间ms  
  20. }  
  21. double calc_sin(double x)  //调用周期函数solve_period的参数  
  22. {    
  23.     return (1 + sin(FACTOR * x)) / 2; //y=1/2(1+sin(a*x))  
  24. }  
  25. double calc_fangbo(double x)  //调用周期函数solve_period的参数  
  26. {  
  27.     //方波函数  
  28.     if(x<=PERIOD/2) return Max;  
  29.     else return Min;  
  30. }  
  31.   
  32. void solve_period(Func *calc) //线程函数为周期函数  
  33. {  
  34.     double x = 0.0;  
  35.     double cache[COUNT];  
  36.     for (int i = 0; i < COUNT; ++i, x += GAP)   
  37.         cache[i] = calc(x);   
  38.     int count = 0;  
  39.     while(1)  
  40.     {  
  41.         unsigned ta = get_time();  
  42.         if (count >= COUNT) count = 0;  
  43.         double r = cache[count++];  
  44.         DWORD busy = r * GAP;  
  45.         while(get_time() - ta < busy) {}  
  46.         Sleep(GAP - busy);  
  47.   }  
  48. }  
  49.   
  50. void solve_linear(Func*)  //线程函数为线性函数,参数为空 NULL  
  51. {  
  52.     const unsigned BUSY =  Ratio * GAP_LINEAR;  
  53.     const unsigned IDLE = (1 - Ratio) * GAP_LINEAR;  
  54.     while(1)  
  55.     {  
  56.         unsigned ta = get_time();  
  57.         while(get_time() - ta < BUSY) {}  
  58.         Sleep(IDLE);  
  59.     }  
  60. }  
  61. //void solve_nonperiod(Func *calc) //非周期函数的处理,暂没实验  
  62. //{  
  63. //  double tb = 0;  
  64. //  while(1)  
  65. //  {  
  66. //    unsigned ta = get_time();  
  67. //    double r = calc(tb);  
  68. //    if (r < 0 || r > 1) r = 1;  
  69. //    DWORD busy = r * GAP;  
  70. //    while(get_time() - ta < busy) {}  
  71. //    Sleep(GAP - busy);  
  72. //    //tb += GAP;  
  73. //    tb += get_time() - ta;  
  74. //  }  
  75. //}  
  76.   
  77. void run(int i=1,double R=0.5,double T=60000,double max=0.9,double min=0.1)  
  78.      //i为输出状态,R为直线函数的值,T为周期函数的周期,max方波最大值,min方波最小值  
  79. {  
  80.     Ratio=R; PERIOD=T; Max=max; Min=min;  
  81.     Func *func[] = {NULL ,calc_sin,calc_fangbo};  //传给Solve的参数,函数指针数组  
  82.     Solve *solve_func[] = { solve_linear, solve_period};  //Solve函数指针数组  
  83.     const int NUM_CPUS = 2;  //双核,通用的可以用下面GetSystemInfo得到cpu数目  
  84.     HANDLE handle[NUM_CPUS];    
  85.     DWORD thread_id[NUM_CPUS]; //线程id  
  86.     //SYSTEM_INFO info;  
  87.     //GetSystemInfo(&info);   //得到cpu数目  
  88.     //const int num = info.dwNumberOfProcessors;  
  89.     switch(i)  
  90.     {  
  91.     case 1: //cpu1 ,cpu2都输出直线  
  92.         {  
  93.             for (int i = 0; i < NUM_CPUS; ++i)  
  94.             {  
  95.                 Func *calc = func[0];  
  96.                 Solve *solve = solve_func[0];  
  97.                 if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  98.                                     (VOID*)calc, 0, &thread_id[i])) != NULL)  //创建新线程  
  99.                 SetThreadAffinityMask(handle[i], i+1); //限定线程运行在哪个cpu上  
  100.             }  
  101.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  102.             break;  
  103.         }  
  104.     case 2: //cpu1直线,cpu2正弦  
  105.         {  
  106.             for (int i = 0; i < NUM_CPUS; ++i)  
  107.             {  
  108.                 Func *calc = func[i];  
  109.                 Solve *solve = solve_func[i];  
  110.                 if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  111.                                     (VOID*)calc, 0, &thread_id[i])) != NULL)  //创建新线程  
  112.                 SetThreadAffinityMask(handle[i], i+1); //限定线程运行在哪个cpu上  
  113.             }  
  114.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  115.             break;  
  116.         }  
  117.         case 3: //cpu1直线,cpu2方波  
  118.         {  
  119.   
  120.             /*Func *calc = func[0]; 
  121.             Solve *solve = solve_func[0];*/  
  122.             if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[0],   
  123.                                 (VOID*)func[0], 0, &thread_id[0])) != NULL)  //创建新线程  
  124.             SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上  
  125.             Func *calc = func[2];  
  126.             Solve *solve = solve_func[1];  
  127.             if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  128.                                 (VOID*)calc, 0, &thread_id[1])) != NULL)  //创建新线程  
  129.             SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上  
  130.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  131.             break;  
  132.         }  
  133.         case 4: //cpu1正弦,cpu2方波  
  134.         {  
  135.             if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[1],   
  136.                                 (VOID*)func[1], 0, &thread_id[0])) != NULL)  //创建新线程  
  137.             SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上  
  138.             Func *calc = func[2];  
  139.             Solve *solve = solve_func[1];  
  140.             if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  141.                                 (VOID*)calc, 0, &thread_id[1])) != NULL)  //创建新线程  
  142.             SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上  
  143.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  144.             break;  
  145.         }  
  146.         defaultbreak;  
  147.     }  
  148. }  
  149.   
  150. void main()  
  151. {  
  152.     run(1,0.5);  //cpu1 ,cpu2都输出50%的直线  
  153.     //run(2,0.5,30000); //cpu1 0.5直线,cpu2正弦周期30000  
  154.     //run(3);  //cpu1直线,cpu2方波  
  155.     //run(4,0.8,30000,0.95,0.5); //cpu1正弦,cpu2 0.95-0.5的方波  
  156. }  

下面更深入讨论,http://www.cnblogs.com/flyinghearts/archive/2011/03/22/1991965.html这篇博文很好,讨论了在双核情况下,每个cpu显示不同的曲线。如下:

控制CPU占用率,不仅仅是出于好玩而已。以前的某些程序,特别是某些老游戏,在新的机器上运行速度太快,必须先给CPU降速,才能顺利运行那些程序,有个共享软件CPUKiller,就是专门弄这个的。

控制CPU占用率,因为要调用Windows的API,要考虑到多核、超线程的情况,要考虑到不同版本的Windows的计时相关的API的精度不同,使问题变得相当复杂,若再考虑其它程序的CPU占用率,则该问题则变得很烦人。(taskmgr调用了一个未公开的API)。

对CPU核数的判断,书上是调用GetProcessorInfo,其实可以直接调用GetSystemInfo,SYSTEM_INFO结构的dwNumberOfProcessors成员就是核数。不知道超线程对这两种方法有什么影响。

如果不考虑其它程序的CPU占用情况,可以在每个核上开一个线程,运行指定的函数,实现每个核的CPU占用率相同

要让CPU的占用率,呈函数 y = calc(t) (0 <= y <= 1, t为时间,单位为ms )分布,只要取间隔很短的一系列点,认为在某个间隔内,y值近似不变。

设间隔值为GAP,显然在指定t值附近的GAP这段时间内,

CPU占用时间为:busy = GAP * calc(t),

CPU空闲时间为:idle = GAP - busy

因此,很容易写出下面这个通用函数:

[cpp]  view plain copy
  1. void solve(Func *calc)  
  2. {  
  3.   double tb = 0;  
  4.   while(1)   
  5.  {  
  6.     unsigned ta = get_time();  
  7.     double r = calc(tb);  
  8.     if (r < 0 || r > 1) r = 1;  
  9.     DWORD busy = r * GAP;  
  10.     while(get_time() - ta < busy) {}  
  11.     Sleep(GAP - busy);  
  12.     tb += GAP;  
  13.   }  
  14. }  

 

如果CPU占用率曲线不是周期性变化,就要对每个t值都要计算一次,否则,可以只计算第一个周期内的各个t值,其它周期的直接取缓存计算结果。

以CPU占用率为正弦曲线为例,显然:y = 0.5 * (1 + sin(a * t + b))

其周期T = 2 * PI / a  (PI = 3.1415927),可以指定T值为60s即60000ms,则

 可以确定a值为 2 * PI / T, 若在这60000ms内我们计算200次(c = 200),则GAP值为 T / c = 300ms.也就是说,只要确定了周期和计算次数,其它几个参数也都确定下来。

代码如下

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cmath>  
  3. #include<windows.h>  
  4.   
  5. static int PERIOD = 60 * 1000; //周期ms  
  6. const int COUNT = 300;  //一个周期计算次数  
  7. const double GAP_LINEAR = 100;  //线性函数时间间隔100ms  
  8. const double PI = 3.1415926535898; //PI  
  9. const double GAP = (double)PERIOD / COUNT; //周期函数时间间隔  
  10. const double FACTOR = 2 * PI / PERIOD;  //周期函数的系数  
  11. static double Ratio = 0.5;  //线性函数的值 0.5即50%  
  12. static double Max=0.9; //方波函数的最大值  
  13. static double Min=0.1; //方波函数的最小值  
  14.   
  15. typedef double Func(double);  //定义一个函数类型 Func*为函数指针  
  16. typedef void Solve(Func *calc);//定义函数类型,参数为函数指针Func*  
  17. inline DWORD get_time()   
  18. {   
  19.     return GetTickCount(); //操作系统启动到现在所经过的时间ms  
  20. }  
  21. double calc_sin(double x)  //调用周期函数solve_period的参数  
  22. {    
  23.     return (1 + sin(FACTOR * x)) / 2; //y=1/2(1+sin(a*x))  
  24. }  
  25. double calc_fangbo(double x)  //调用周期函数solve_period的参数  
  26. {  
  27.     //方波函数  
  28.     if(x<=PERIOD/2) return Max;  
  29.     else return Min;  
  30. }  
  31.   
  32. void solve_period(Func *calc) //线程函数为周期函数  
  33. {  
  34.     double x = 0.0;  
  35.     double cache[COUNT];  
  36.     for (int i = 0; i < COUNT; ++i, x += GAP)   
  37.         cache[i] = calc(x);   
  38.     int count = 0;  
  39.     while(1)  
  40.     {  
  41.         unsigned ta = get_time();  
  42.         if (count >= COUNT) count = 0;  
  43.         double r = cache[count++];  
  44.         DWORD busy = r * GAP;  
  45.         while(get_time() - ta < busy) {}  
  46.         Sleep(GAP - busy);  
  47.   }  
  48. }  
  49.   
  50. void solve_linear(Func*)  //线程函数为线性函数,参数为空 NULL  
  51. {  
  52.     const unsigned BUSY =  Ratio * GAP_LINEAR;  
  53.     const unsigned IDLE = (1 - Ratio) * GAP_LINEAR;  
  54.     while(1)  
  55.     {  
  56.         unsigned ta = get_time();  
  57.         while(get_time() - ta < BUSY) {}  
  58.         Sleep(IDLE);  
  59.     }  
  60. }  
  61. //void solve_nonperiod(Func *calc) //非周期函数的处理,暂没实验  
  62. //{  
  63. //  double tb = 0;  
  64. //  while(1)  
  65. //  {  
  66. //    unsigned ta = get_time();  
  67. //    double r = calc(tb);  
  68. //    if (r < 0 || r > 1) r = 1;  
  69. //    DWORD busy = r * GAP;  
  70. //    while(get_time() - ta < busy) {}  
  71. //    Sleep(GAP - busy);  
  72. //    //tb += GAP;  
  73. //    tb += get_time() - ta;  
  74. //  }  
  75. //}  
  76.   
  77. void run(int i=1,double R=0.5,double T=60000,double max=0.9,double min=0.1)  
  78.      //i为输出状态,R为直线函数的值,T为周期函数的周期,max方波最大值,min方波最小值  
  79. {  
  80.     Ratio=R; PERIOD=T; Max=max; Min=min;  
  81.     Func *func[] = {NULL ,calc_sin,calc_fangbo};  //传给Solve的参数,函数指针数组  
  82.     Solve *solve_func[] = { solve_linear, solve_period};  //Solve函数指针数组  
  83.     const int NUM_CPUS = 2;  //双核,通用的可以用下面GetSystemInfo得到cpu数目  
  84.     HANDLE handle[NUM_CPUS];    
  85.     DWORD thread_id[NUM_CPUS]; //线程id  
  86.     //SYSTEM_INFO info;  
  87.     //GetSystemInfo(&info);   //得到cpu数目  
  88.     //const int num = info.dwNumberOfProcessors;  
  89.     switch(i)  
  90.     {  
  91.     case 1: //cpu1 ,cpu2都输出直线  
  92.         {  
  93.             for (int i = 0; i < NUM_CPUS; ++i)  
  94.             {  
  95.                 Func *calc = func[0];  
  96.                 Solve *solve = solve_func[0];  
  97.                 if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  98.                                     (VOID*)calc, 0, &thread_id[i])) != NULL)  //创建新线程  
  99.                 SetThreadAffinityMask(handle[i], i+1); //限定线程运行在哪个cpu上  
  100.             }  
  101.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  102.             break;  
  103.         }  
  104.     case 2: //cpu1直线,cpu2正弦  
  105.         {  
  106.             for (int i = 0; i < NUM_CPUS; ++i)  
  107.             {  
  108.                 Func *calc = func[i];  
  109.                 Solve *solve = solve_func[i];  
  110.                 if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  111.                                     (VOID*)calc, 0, &thread_id[i])) != NULL)  //创建新线程  
  112.                 SetThreadAffinityMask(handle[i], i+1); //限定线程运行在哪个cpu上  
  113.             }  
  114.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  115.             break;  
  116.         }  
  117.         case 3: //cpu1直线,cpu2方波  
  118.         {  
  119.   
  120.             /*Func *calc = func[0]; 
  121.             Solve *solve = solve_func[0];*/  
  122.             if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[0],   
  123.                                 (VOID*)func[0], 0, &thread_id[0])) != NULL)  //创建新线程  
  124.             SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上  
  125.             Func *calc = func[2];  
  126.             Solve *solve = solve_func[1];  
  127.             if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  128.                                 (VOID*)calc, 0, &thread_id[1])) != NULL)  //创建新线程  
  129.             SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上  
  130.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  131.             break;  
  132.         }  
  133.         case 4: //cpu1正弦,cpu2方波  
  134.         {  
  135.             if ((handle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve_func[1],   
  136.                                 (VOID*)func[1], 0, &thread_id[0])) != NULL)  //创建新线程  
  137.             SetThreadAffinityMask(handle[0], 1); //限定线程运行在哪个cpu上  
  138.             Func *calc = func[2];  
  139.             Solve *solve = solve_func[1];  
  140.             if ((handle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,   
  141.                                 (VOID*)calc, 0, &thread_id[1])) != NULL)  //创建新线程  
  142.             SetThreadAffinityMask(handle[1], 2); //限定线程运行在哪个cpu上  
  143.             WaitForSingleObject(handle[0],INFINITE);   //等待线程结束  
  144.             break;  
  145.         }  
  146.         defaultbreak;  
  147.     }  
  148. }  
  149.   
  150. void main()  
  151. {  
  152.     run(1,0.5);  //cpu1 ,cpu2都输出50%的直线  
  153.     //run(2,0.5,30000); //cpu1 0.5直线,cpu2正弦周期30000  
  154.     //run(3);  //cpu1直线,cpu2方波  
  155.     //run(4,0.8,30000,0.95,0.5); //cpu1正弦,cpu2 0.95-0.5的方波  
  156. }  

效果如图:

                 补充:我本人的电脑是Win10系统 i7-4700八核处理器,无奈不知道为什么使用以上方法很难实现,以上的效果都是我用虚拟机弄的winXP实现的。

比如当我用上面的多核的方法的时候,我把处理器核数改为8会出现如下的效果:

             

发现前四个处理器满载,其余也有不定占有率,我怀疑是不是这是win10的负载平衡导致的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值