• 《编程之美》之CPU曲线


    1.CPU相关:(摘自MSDN——Processor Groups

    Systems with more than one physical processor or systems with physical processors that have multiple cores provide the operating system with multiple logical processors. A logical processor is one logical computing engine from the perspective of the operating system, application or driver. A core is one processor unit, which can consist of one or more logical processors. A physical processor can consist of one or more cores. A physical processor is the same as a processor package, a socket, or a CPU.

    从操作系统(或者是应用程序、驱动)的角度看,一个逻辑处理器就是一个逻辑计算引擎。一个内核就是一个处理单元,它可以由一个或多个逻辑处理器组成。一个物理处理器可以由一个或多个内核组成。

    以我的电脑为例,CPU为i3-2330M,2.2GHz,2个内核,4个逻辑处理器(也叫做双核四线程)。2个内核拥有2*2个逻辑处理器,得益于Intel的超线程技术(HT),该技术可实现在一个实体处理器中提供两个逻辑线程,也就是说一个处理器可模拟出两个处理器。在Windows任务管理器里就可以体现出来。可以看出,有4个小窗口。

    注意:若其中一个逻辑处理器满负荷运转,则CPU的使用率为25%,若控制一个逻辑处理器的使用率为50%,则CPU的使用率为12.5%。



    2.直线CPU

    要控制CPU的使用率,就必须了解一个函数——Sleep(),该函数的作用是让程序让出CPU时间,除了Sleep,其他的操作都会占用CPU时间。

    ①根据CPU速度估算

    i3-2330M的速度达到2.2GHz,一个for循环for(i=0;i<n;i++)转换成汇编语句:

    loop:

    mov dx i;将i置入dx寄存器

    inc dx;将dx寄存器加1

    mov i dx;将dx中的值赋回i

    cmp i n;比较i和n

    jl loop;i小于n时则重复循环

    共5句汇编,现代CPU每个时钟周期可执行两条以上的指令,那么每秒可执行for循环的次数为2.2G*2/5次,执行代码如下:

    void LineCPU1()
    {
    	SetThreadAffinityMask(GetCurrentThread(), 8); 
    	long i;
    	while(1)
    	{
    		for(i=0;i<8800000;i++);
    		Sleep(10);
    	}
    }
    这里选用10ms是因为10ms比较接近Windows调度时间片,若该值太大,会使得曲线不平滑,一下很高,一下很低;若该值太小,会使得线程被频繁地唤醒和挂起,无形中又增加了内核时间不确定性的影响。

    从执行效果可看到,该程序(test2.exe)CPU使用率为18%,大于我们希望的12.5%,我将n改为4400000,使用率会低至14%,但还是不是12.5%。可见这种方法比较粗糙,且只适用于特定频率的CPU,具有CPU差异性。(笔记本出于省电的考虑,CPU的时钟频率可能会变化)

    ②利用GetTickCount()消除CPU差异性

    GetTickCount()函数可以得到“系统启动到现在”所经历的毫秒数,最多可统计到49.7天,执行效果:平均CPU使用率基本可维持在12.5上下

    void LineCPU2()
    {
    	SetThreadAffinityMask(GetCurrentThread(), 8);
    	int busyTime = 100;
    	int idleTime = busyTime;
    	long startTime = 0;
    	while(1)
    	{
    		startTime = GetTickCount();
    		while((GetTickCount() - startTime) <= busyTime);
    		Sleep(idleTime);
    	}
    }

    以上两种方法都是假设只有该进程运行在逻辑处理器上,但事实上系统运行时会有其他进程也在运行,若其他进程占用了5%,那么我们的程序就应该占用45%。那么如何解决这个问题呢。

    ③PerformanceCounter类

    PerformanceCounter是.Net类库中的一个类(通过它可以很方便地获取当前的各种性能数据,包括CPU使用率),所以需要用C#来写,需要命名空间using System.Diagnostics,该程序没怎么具体去试

    PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total");       
    while (true)
    {
        if (pc.NextValue() > 18)
            System.Threading.Thread.Sleep(10);
    }

    3.正弦CPU

    有了以上的铺垫,那么正弦的CPU曲线就很容易啦

    void SinCPU()
    {
    	SetThreadAffinityMask(GetCurrentThread(), 8);  
    	const double SPLIT = 0.01;
    	const int COUNT =200;
    	const double PI = 3.14159265;
    	const int INTERVAL = 300;
    
    	int busySpan[COUNT];
    	int idleSpan[COUNT];
    	int half = INTERVAL/2;
    	double rad =0.0;
    	for(int i=0;i<COUNT;i++)
    	{
    		busySpan[i] = (int)(half+(sin(PI*rad)*half/2));
    		idleSpan[i] = INTERVAL - busySpan[i];
    		rad += SPLIT;
    	}
    
    	long startTime = 0;
    	int j = 0;
    	while(1)
    	{
    		j = j%COUNT;
    		startTime = GetTickCount();
    		while((GetTickCount() - startTime)<=busySpan[j]);
    		Sleep(idleSpan[j]);
    		j++;
    	}
    }



    4.指定某个处理器上运行

    SetThreadAffinityMask(hThreaddwThreadAffinityMask)函数的作用是指定该线程在某一个逻辑处理器上运行,每个处理器代表1bit,即1代表第1个处理器,2代表第2个处理器,4代表第3个处理器,8代表第4个处理器,从下面两张图可看出区别,一个是完整的正弦,一个是有缺口的正弦


    当第一个正弦有缺口时,第二、第三个处理器有出现相应的峰值,可见当一个程序在某个处理器中接近满负荷时,会被分配到另外几个处理器中,以减小处理器的压力


    注:SetThreadAffinityMask(hThreaddwThreadAffinityMask)、Sleep()、GetTickCount()函数需要"Windows.h"头文件,数学函数sin()需要"math.h"头文件,CPU的频率会随着供电和负载情况的变化而变化。

  • 相关阅读:
    [翻译] SVProgressHUD
    使用CoreData [4]
    Android学习笔记之AndroidManifest.xml文件解析
    Android 版本自动更新
    两个android程序间的相互调用(apk互调)
    Android 生成含签名文件的apk安装包
    【已解决】Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8
    android adt与android sdk有什么关系,他们在开发中各起到什么作用
    Please ensure that adb is correctly located at……问题解决方案
    安装Android SDK时,点击SDK Manager.exe闪退,并且jdk的环境变量是对的。
  • 原文地址:https://www.cnblogs.com/season-peng/p/6713563.html
Copyright © 2020-2023  润新知