一,相关函数介绍
1. sleep ()———这个方法能让当前线程"停”下来。
2. waitForsingleobject ( )…自己停下来,等待某个事件发生
3. GetTickCount ( )-有人把Tick翻译成"嘀嗒”,很形象。
4.QueryPerformanceFrequency()、QueryPerformanceCounter ( )-让你访问到精
度更高的 CPU 数据。
5. timeGetsystemTime ( )是另一个得到高精度时间的方法。
6. Performancecounter——效能计数器。
7. GetProcessorInfo () /setThreadAffinityMask( ) 。遇到多核的问题怎么办呢?这两
个方法能够帮你更好地控制CPU。
8. GetCPUTickCount ()。想拿到CPU核心运行周期数吗﹖用用这个方法吧。
二, 讲解
先从简单的入手,让cpu占用率稳定在50%
当程序陷入死循环的时候,cpu占用率是100%,所以我们要让cpu一半时间在循环,简单来说就是
1.将程序放在cpu上运行
2.while{
for(;;) 循环一半
Sleep() 休息一半
}
sleep(): 这个方法可以让当前线程暂停执行一段时间。它接受一个参数,表示暂停的时间长度,单位可以是毫秒、秒或其他时间单位。调用sleep()方法会使线程进入阻塞状态,暂停执行,直到指定的时间间隔过去后再继续执行。
因为一次循环所占用的时间太小,所以我们需要知道循环几次==sleep(1),书中最后选取的是sleep(10)的搭配,下面是书中给出的解答
int main ( ) for( ; ; ) for(int i = 0; i <9600000; i++); sleep (10) ; return 0;
在不断调整9 600 000的参数后,我们就可以在一台指定的机器上获得一条大致稳定的50% CPU占用率值线。
尽量减少sleep/awake的频率,如果频繁发生,影响则会很大,因为此时优先级更高
的操作系统内核调度程序会占用很多CPU运算时间。无法适应差异性,换一台电脑换一个数据
int busyTime = 10;//10 ms int idleTime = busyTime; // same ratio will lead to 50% cpu usage Int64 startTime = 0; while (true) { startTime = GetTickCount ( ) ;//busy loop的循环 while ( (GetTickCount() - startTime) <= busyTime) ; //idle loop sleep (idleTime) ;
GetTickCount(): 这个函数是Windows操作系统提供的方法,用于获取系统启动以来经过的毫秒数。它返回一个32位无符号整数,可以用于测量时间间隔或计算程序执行时间。GetTickCount()函数通常用于粗略测量时间,精度较低。ms级别
但是在实际问题中,CPU上运行的程序可远远不止这个程序,还会有很多其他的东西,如果其他的进程占用了CPU的占比
static void MakeUsage(float level){ PerformanceCounter p = new PerformanceCounter("Processor","% Processor Time",Total"); while (true) if (p.NextValue () > level) system . Threading . Thread.sleep(10);
PerformanceCounter: 效能计数器是一种用于测量系统性能的工具。它可以提供各种系统资源的使用情况,如CPU利用率、内存使用情况、磁盘IO等。通过使用效能计数器,可以监控系统的性能状况,并进行性能优化和故障排查。
到这里我们可以开始不当人了!开始CPU画正弦!
整个过程划分为两部进行,先生成正弦函数的数组,然后根据数组来分配CPU中
实际上这个程序并不能很优雅的画出曲线,因为其实我们没用办法解决cpu其他进程对程序的占用,如果要考虑这一点,我们需要引入 PerformanceCounter,做一些修正#include <iostream> #include <windows.h> #include <stdlib.h> #include <math.h> using namespace std; const double SPLIT=0.01; const int COUNT=200; const double PI=3.14159265; const int INTERVAL=300; DWORD busySpan[COUNT]; DWORD idleSpan[COUNT]; void thread1(){ DWORD startTime=0; DWORD busyTime=50; DWORD idleTime=busyTime; while(true){ startTime=GetTickCount(); while((GetTickCount()-startTime)<=busyTime); Sleep(idleTime); } } void thread2(){ DWORD startTime=0; int j=0; while(true){ j=j%COUNT; startTime=GetTickCount(); while((GetTickCount()-startTime)<=busySpan[j]); Sleep(idleSpan[j]); j++; } } int main(){ int half=INTERVAL/2; double radian=0.0; for(int i=0;i<COUNT;i++){ busySpan[i]=(DWORD)(half+(sin(PI*radian)*half)); idleSpan[i]=INTERVAL-busySpan[i]; radian+=SPLIT; } HANDLE handle; DWORD threadID; if((handle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&thread2,0,0,&threadID))!=NULL) SetThreadAffinityMask(handle,1); WaitForSingleObject(handle,INFINITE); return 1; }
三,拓展函数
waitForSingleObject(): 这个函数是Windows操作系统提供的方法,用于等待一个对象的状态变为可用。它可以用于线程间的同步和互斥操作。调用waitForSingleObject()方法会使当前线程停下来,等待指定的事件发生或指定的对象状态变为可用。
QueryPerformanceFrequency()和QueryPerformanceCounter(): 这两个函数是Windows操作系统提供的方法,用于访问高精度的CPU计时器。QueryPerformanceFrequency()返回CPU计时器的频率,单位为每秒的计数数。QueryPerformanceCounter()返回当前CPU计时器的计数值。通过这两个函数,可以获得更高精度的时间信息,用于性能测量和计时操作。
timeGetSystemTime(): 这个函数是Windows操作系统提供的方法,用于获取系统的当前时间。它返回一个SYSTEMTIME结构体,包含了年、月、日、时、分、秒等时间信息。timeGetSystemTime()函数可以提供较高精度的系统时间,比GetTickCount()函数更准确。
GetProcessorInfo()和SetThreadAffinityMask(): 这两个函数是Windows操作系统提供的方法,用于处理多核处理器的相关问题。GetProcessorInfo()函数可以获取CPU的相关信息,包括核心数、线程数等。SetThreadAffinityMask()函数可以设置线程的CPU亲和性,即指定线程在哪些CPU核心上运行。
这里对于其中的waitForSingleObject()做拓展
该函数的原型如下:
DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
参数说明:
hHandle
:要等待的对象的句柄(handle),可以是一个线程句柄、进程句柄、互斥对象、事件对象等。dwMilliseconds
:等待时间的毫秒数。如果设置为 INFINITE,表示无限等待,直到对象状态变为可用或事件发生。
waitForSingleObject()
函数的返回值是一个 DWORD 类型的值,表示等待的结果。可能的返回值包括:
WAIT_OBJECT_0
(0):指定的对象已经变为可用。WAIT_TIMEOUT
(258):等待超时。在指定的时间内,对象的状态没有发生变化。WAIT_FAILED
(~0):等待失败。通常表示发生了错误。在使用
waitForSingleObject()
函数时,您需要注意以下几点:
- 要等待的对象必须是可等待的对象,如线程句柄、事件对象、互斥对象等。
- 对象的状态必须能够通过等待来改变,否则等待永远不会结束。
- 等待的时间可以是一个固定的时间,也可以是无限等待。
此外,Windows 还提供了其他类似的函数,如
WaitForMultipleObjects()
,用于等待多个对象的状态变为可用。这些函数在多线程编程和同步处理中非常有用。