编程之美读书笔记1.1——让cpu占用率曲线听你的指挥(代码片段)

-柚子皮- -柚子皮-     2023-01-24     725

关键词:

http://blog.csdn.net/pipisorry/article/details/36189155

 
<strong><span style="font-size:48px;color:#ff0000;">问题:</span></strong>写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率。

如果机器是多CPU,上面的程序会出现什么结果?如何在多个CPU时显示同样的状态?例如,在双核的机器上,如果让一个单线程的程序死循环,能让两个CPU的使用率达到50%的水平么?为什么?多CPU的问题首先需要获得系统的CPU信息。可以使用GetProcessorInfo()获得多处理器的信息,然后指定进程在哪一个处理器上运行。其中指定运行使用的是SetThreadAffinityMask()函数。

书中提到两个重要的API,GetProcessorInfo()与SetThreadAffinityMask()。经查询MSDN,GetProcessorInfo()是Windows Server上的API,在PC机上不好用,所以可以尝试GetSystemInfo()来获得核数。

实际上在Windows平台上直接用任务管理器就可以查看,任务管理器上会用四个窗口来显示CPU的使用情况(Windows7 酷睿i5-3230M)


四核都显示正弦曲线算法:

参考代码:

/*********************************************************************************************/
/* 控制cpu占用率曲线(50%直线、1~100任意直线、正弦曲线)皮皮 2014-6-30 */
/********************************************************************************************/
#include <Windows.h>
#include <stdio.h>
#include <math.h>
using namespace std;

const int SAMPLE_NUM = 200;
DWORD busy_time[200];
const DWORD TOTAL_TIME_SLICE = 100; //每隔100ms取下一个采样点,让cpu工作在对应振幅的时间
const DWORD HALF_TOTAL_TIME_SLICE = TOTAL_TIME_SLICE/2;
//sine 曲线
void sine()
DWORD pre_time;
for(int i = 0 ; ; i = (i+1)%SAMPLE_NUM )
pre_time = GetTickCount();
while( (GetTickCount() - pre_time) <= busy_time[i]);//cpu忙
Sleep(TOTAL_TIME_SLICE - busy_time[i]);//cpu闲




const double PI_L = 0.031415926535;
//对sine采样
void sine_sampling()
for(int i = 0 ; i < SAMPLE_NUM ; i++)
busy_time[i] = (DWORD)( sin( PI_L*i )*HALF_TOTAL_TIME_SLICE + HALF_TOTAL_TIME_SLICE );//busy_time值范围 (-1~1) *50+50 = (0~100)
//printf("busy_time[%d] = %d\\n",i,busy_time[i]);




void main()
sine_sampling();

//printf("CurrentProcessorNumber : %d\\n",(int)GetCurrentProcessorNumber());
SYSTEM_INFO info;
    GetSystemInfo(&info); //调用API函数来获取计算机硬件的信息
printf("dwNumberOfProcessors : %d\\n",info.dwNumberOfProcessors);//cpu核数

DWORD dwThreadId;
HANDLE hThread;
int coreNum = info.dwNumberOfProcessors;
for(int i = 0 ; i < coreNum ; i ++)
hThread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)sine,0,0,&dwThreadId);
SetThreadAffinityMask(hThread,1<<i);//针对cpu核i(from 0)

    WaitForSingleObject(hThread, INFINITE); //传入INFINITE表示无限等待


代码部分解释:

1.CreateThread

函数功能:创建线程

函数原型:

CreateThread(
    __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in      SIZE_T dwStackSize,
    __in      LPTHREAD_START_ROUTINE lpStartAddress,
    __in_opt __deref __drv_aliasesMem LPVOID lpParameter,
    __in      DWORD dwCreationFlags,
    __out_opt LPDWORD lpThreadId
    );

函数说明:

第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。

第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。

第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。

第四个参数是传给线程函数的参数。

第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()

第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。

函数返回值:成功返回新线程的句柄,失败返回NULL 


 2.WaitForSingleObject

函数功能:等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。

函数原形:

WaitForSingleObject(
    __in HANDLE hHandle,
    __in DWORD dwMilliseconds
    );

函数说明:

第一个参数为要等待的内核对象。

第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。

因为线程的句柄在线程运行时是未触发的,线程结束运行,句柄处于触发状态。所以可以用WaitForSingleObject()来等待一个线程结束运行。

函数返回值:在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED


3.SetThreadAffinityMask()

函数功能:Sets a processor affinity mask for the specified thread.

函数原形:

WaitForSingleObject(
    __in HANDLE hHandle,
    __in DWORD dwMilliseconds
    );

函数说明:

这个函数的参数有两个,第一个是执行任务的句柄,第二个是核的掩蔽码。

掩蔽码的使用规则是如果最低位置1,就将任务分派给编号为0的核,如果次低位置1,就将任务分派给编号为1的核。

如果掩蔽码设置为0xC,即编号为2, 3的核被置为1,线程就会在这两个核上切换。

more:

进程与指定cpu绑定:SetProcessAffinityMask(GetCurrentProcess(), dwMask);

线程与指定cpu绑定:SetThreadAffinityMask(GetCurrentThread(),dwMask);

dwMask为CPU序号的或运算值:1(0001)代表只运行在CPU1,2(0010)代表只运行在CPU2,3(0011)代表可以运行在CPU1和CPU2,以此类推。

ref: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686247(v=vs.85).aspx


结果截图:





附:

1.TOTAL_TIME_SLICE 的计算

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

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

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

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

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

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

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值都要计算一次,否则,可以只计算第一个周期内的各个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.也就是说,只要确定了周期和计算次数,其它几个参数也都确定下来。


2.CPU亲缘性(Affinity)介绍

按照默认设置,当系统将线程分配给处理器时,Windows使用软亲缘性来进行操作。这意味着如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。

有一种新的计算机结构,称为NUMA(非统一内存访问),在该结构中,计算机包含若干块插件板,每个插 件板上有4个CPU和它自己的内存区。
当CPU访问的内存是它自己的插件板上的内存时,NUMA系统运行的性能最好。如果CPU需要访问位于另一个插件板上的内 存时,就会产生巨大的性能降低。在这样的环境中,就需要限制来自一个进程中的线程在共享同一个插件版的CPU上运行。为了适应这种计算机结构的需要,Windows允许你设置进程和线程的亲缘性。换句话说,你可以控制哪个CPU能够运行某些线程。这称为硬亲缘性。请注意,子进程可以继承进程的亲缘性。

注意:

(1)无论计算机中实际拥有多少个CPU,Windows98及以前系统只使用一个CPU,上述API不被支持。

(2)在大多数环境中,改变线程的亲缘性就会影响调度程序有效地在 各个CPU之间移植线程的能力,而这种能力可以最有效地使用CPU时间。


3.CreateThread()函数

它是Windows提供的API接口,在C/C++语言另有一个创建线程的函数_beginthreadex(),在很多书上(包括《Windows核心编程》)提到过尽量使用_beginthreadex()来代替使用CreateThread(),这是为什么?http://blog.csdn.net/morewindows/article/details/7421759


ref:

http://blog.csdn.net/pipisorry/article/details/36189155

http://blog.csdn.net/morewindows/article/details/7421759

http://www.cnblogs.com/foreverinside/p/3577273.html

http://www.cnblogs.com/flyinghearts/archive/2011/03/22/1991965.html

http://blog.csdn.net/u012370255/article/details/28232153

编程之美之让cpu占用率听你指挥

昨天在bbs上淘到了这本编程之美。顺手刷了第一章,很有意思。第一章的要求是要控制CPU曲线,绘制出对应的形状。拿到这个问题,我的第一反应是,是不是有这么一个API,能在任务管理器上的对应区域直接绘制图形呢?然后就... 查看详情

把cpu“玩”起来(代码片段)

前言从开始学习编程之后,就渐渐痴迷于技术,平时遇到购书满减活动时就忍不住买一堆书。前两天闲着无聊,翻开了去年买的《编程之美》,目录里的“让CPU占用率听你指挥”吸引力我的眼球。这一年来捣鼓数据挖掘和... 查看详情

生成cpu使用率sin曲线控制cpu使用率编程之美

入职Oracle以后想着把之前写过的《编程之美》中控制CPU使用率曲线的程序再写一边,可是总是由于入职须要学习的东西太多,没有时间。程序早就写好了。最终有机会贴出来了。o(∩∩)o..最早的时候我採用C实现的效果并不好。... 查看详情

cpu占用率曲线-笔记

...可以从->性能栏看到CPU占用率的曲线的变化。今天看了编程之美的第一章第一节,看到对电脑cpu占用率的控制,控制CPU占用率曲线变化,达到特定的效果。cpu占用率曲线的刷新频率为1秒。要使在某一时刻CPU占用率达到目的中的... 查看详情

cpu占用率让曲线指挥

...11月3日)写一个程序,让用户来决定windows任务管理器的cpu占用率。程序越简单越好,计算机语言不限。1.cpu的占用率固定在50%,为一条直线;2.cpu的占用为一条直线3.cpu的占用状态为一条正弦曲线。 解题思路:要操纵cpu的使用曲... 查看详情

编程之美读书笔记1.8-小飞的电梯调度算法

http://blog.csdn.net/pipisorry/article/details/36688019问题:亚洲微软研究院所在的希格玛大厦一共同拥有6部电梯。在高峰时间,每层都有人上下。电梯每层都停。实习生小飞经常会被每层都停的电梯弄的非常不耐烦。于是他提出了这样一... 查看详情

java多线程编程核心技术读书笔记-线程通信

  线程是操作系统中独立的个体,但是这些个体如果无法经过特殊的处理就不能成为一个整体。线程间通信可以实现线程间的信息互换、相互唤起等功能,是系统的交互性更加强大,大大提高CPU的利用率,同时还能让开发者对... 查看详情

怎么让cpu占用率达到100%

命令:foriin`seq1$(cat/proc/cpuinfo|grep"physicalid"|wc-l)`;doddif=/dev/zeroof=/dev/null&done命令拆解说明:cat/proc/cpuinfo|grep"physicalid"|wc-l获得CPU的个数,seq1N有几个CPU生成几个数字foriin`seq1N`;就 查看详情

如何监视某一进程的cpu占用率

CPU使用率其实就是你运行的程序占用的CPU资源,表示你的机器在某个时间点的运行程序的情况。使用率越高,说明你的机器在这个时间上运行了很多程序,反之较少。使用率的高低与你的CPU强弱有直接关系。现代分时多任务操作... 查看详情

linux服务器cpu占用率800%左右...

...如何排查呢?实在没招了!参考技术A在Linux系统中,CPU利用率的最大值是100%。但是,当一个进程使用了多个CPU核心时,它的CPU利用率可能会显示为超过100%的数字。例如,如果一个进程使用了4个CPU核心,则它的CPU利用率可能会显... 查看详情

cpu占用率

toptop命令显示的cpu占用率是所有cpu占用率之和执行top命令后,再按大键盘的1键,即可看到当前有多少cpu,每个cpu的占用率情况cat/proc/cpuinfo可查看cpu信息,有几个核等等cpu占用率较高,如何降低cpu占用率,一般如果轮询太频繁,c... 查看详情

java并发编程实战读书笔记3(代码片段)

1、ConcurrentModificationException当容器在迭代过程中被其他线程修改时,就会抛出该异常。想要避免该以后该异常,就需要在迭代的过程中持有该容器的锁。但是长时间持有容器的锁会降低程序的可伸缩性,持有锁的时间... 查看详情

java并发编程实战读书笔记3(代码片段)

1、ConcurrentModificationException当容器在迭代过程中被其他线程修改时,就会抛出该异常。想要避免该以后该异常,就需要在迭代的过程中持有该容器的锁。但是长时间持有容器的锁会降低程序的可伸缩性,持有锁的时间... 查看详情

为什么我显卡占用率一直是0

使用率为零有两种情况:一、正常,在没有使用任何软件时候;二、不正常、在使用软件,并且电脑非常卡情况下为零;第一种就接介绍了,简单说下第二种:1、WIN7出问题认机器,解决办法从做系统;2、可能由于病毒引起,解... 查看详情

数学之美读书笔记——自然语言处理教父和他的弟子们

    查看详情

求高手解cpu占用率过高,导致温度高怎么办。

...过高导致的,下了个鲁大师看,玩玩CS和实况足球2010CPU占用率就有55%和65%,正常情况下是没有什么占有率的,因为我把才把硬盘都格式化了一次。游戏玩上5分钟,CPU温度就会上到70度左右,显卡温度也会跟着涨上去,主板硬盘温... 查看详情

java多线程cpu占用率高的问题

...多线程下载的小程序,我创建了10个线程同时下载,cpu占用率很高,不知道是什么原因,请大家帮忙,主要代码如下publicclasstestimplementsRunnable publicInputStreamin=null; publicFileOutputStreamout=null; @Override publicvoidrun() //打开网络连接获取in... 查看详情

深度解读鸿蒙轻内核cpu占用率(代码片段)

摘要:CPUP(CentralProcessingUnitPercentage,CPU占用率)分为系统CPU占用率和任务CPU占用率。用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。通过系统中各个任务的CPU占用情况,判断各个任务... 查看详情