不当人!用cpu占用曲线画正弦函数???

读书笔记性质博客
《编程之美》.pdf文档全文免费阅读、在线看 (book118.com)

一,相关函数介绍

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中

#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;
}
实际上这个程序并不能很优雅的画出曲线,因为其实我们没用办法解决cpu其他进程对程序的占用,如果要考虑这一点,我们需要引入 PerformanceCounter,做一些修正

三,拓展函数 

  1. waitForSingleObject(): 这个函数是Windows操作系统提供的方法,用于等待一个对象的状态变为可用。它可以用于线程间的同步和互斥操作。调用waitForSingleObject()方法会使当前线程停下来,等待指定的事件发生或指定的对象状态变为可用。

  2. QueryPerformanceFrequency()和QueryPerformanceCounter(): 这两个函数是Windows操作系统提供的方法,用于访问高精度的CPU计时器。QueryPerformanceFrequency()返回CPU计时器的频率,单位为每秒的计数数。QueryPerformanceCounter()返回当前CPU计时器的计数值。通过这两个函数,可以获得更高精度的时间信息,用于性能测量和计时操作。

  3. timeGetSystemTime(): 这个函数是Windows操作系统提供的方法,用于获取系统的当前时间。它返回一个SYSTEMTIME结构体,包含了年、月、日、时、分、秒等时间信息。timeGetSystemTime()函数可以提供较高精度的系统时间,比GetTickCount()函数更准确。

  4. 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(),用于等待多个对象的状态变为可用。这些函数在多线程编程和同步处理中非常有用。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值