CPU多核控速
初学者很多对自己开发的软件使用硬件资源的时候并不注意,造成写出的东西不是很满意。
一般有两种情况:
1.写的都是同步单线程任务,不管你电脑有多少个核都不关我事 我就用你1个核所以不管怎么样都不会把CPU吃满。
这样的例子还是比较多的,在CPU出多核之后很多软件陆续已经将这些问题进行了修复,不过也还有这样的情况。
拿我常用的金山快盘同步盘这个软件来说吧,他在要进行一次同步任务前要先下载一份服务器端文件版本信息的比对数据,所以当我点立即同步的时候或者刚打开软件的时候他会马上使用网络进行下载(任务管理器或很多流量监控软件都可以监控到),下载完成后进行文件版本对比任务找出需要更新的文件,这个时候在 任务管理器 里的进程中可以看到金山快盘会很快占用300-500M左右的内存(这个视个人电脑硬件配置和这个金山快盘用户文件多少而变化)CPU利用率立马飙到50%(我用的这台电脑是双核的)而且只有一个核的利用率到达很高另一个核在睡觉。这种状态一直持续很长一段时间不怎么变化(可能我的文件数量比较多所以这个时间就会比较长)。
2.多线程任务不控制CPU利用率。
很多朋友写程序的时候可能比较少用到多任务多线程开发 或者 搞不好这个程序中的多任务多线程只会用一会儿而且很快就能完成这个作业,所以用到的时候也没注意这么多。
经常使用多任务多线程开发的朋友应该是比较清楚的,不需要看这个了;
咱们先看一下控速与不控诉的区别,对比下面两张图就可以很明白的看出来了。
CPU不受控的情况下开启4条线程跑立马就把CPU吃满了,而且居高不下,造成电脑卡的不行无法进行别的作业。
受控的情况:
看完图就很明白情况了吧!代码是最好交流的方式,那咱们来看一下代码:
基本任务接口:
public interface ICpuManagementTask
{
void DoWork();
void DoWork(object a);
}
ICpuManagementTask
模拟作业,实现任务接口进行作业:
public class ApplictionClass : ICpuManagementTask
{ public ApplictionClass(out ICpuManagementTask icmt)
{
icmt = this;
} public void DoWork()
{
// Thread Code
do
{
int a = ;
for (int i = ; i < ; i++)
{
a = i;
}
//System.Threading.Thread.Sleep(1);
//Console.WriteLine("Task is Running " + mesg + "Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId); } while (true);
} public void DoWork(object mesg)
{
// Thread Code
do
{
int a = ;
for (int i = ; i < ; i++)
{
a = i;
}
//System.Threading.Thread.Sleep(1);
//Console.WriteLine("Task is Running " + mesg + "Id: " + System.Threading.Thread.CurrentThread.ManagedThreadId); } while (true);
}
}
模拟基本业务
模拟不受控实现方式:
/// <summary>
/// 不受控的异步执行
/// </summary>
public void Test1(ICpuManagementTask icmt)
{
System.Threading.Tasks.Task T1 = new System.Threading.Tasks.Task(new Action(icmt.DoWork));
T1.Start(); System.Threading.Tasks.Task T2 = new System.Threading.Tasks.Task(new Action(icmt.DoWork));
T2.Start(); System.Threading.Tasks.Task T3 = new System.Threading.Tasks.Task(new Action(icmt.DoWork));
T3.Start(); System.Threading.Tasks.Task T4 = new System.Threading.Tasks.Task(new Action(icmt.DoWork));
T4.Start(); }
不受控TEST
前面这些都是很简单的,有点OO思想的一看就明白了不需要什么解释的。
既然要让任务占用硬件资源受控制那肯定是需要一些处理的,要跑的作业相当于托管在一个“容器”里面暂时叫他“自动管理CPU”吧,接下来先看一下这个“容器”

看到这个就很简单了吧!其实并没有什么神秘的,无非就是做两个事 一、创建任务 二、管理CPU使用率进行任务作业
咱们一个个看,首先看看这个枚举,他是自定义的几个模式对应当需要挂起线程时处理的事
public enum CpuManagementModelEnum
{
None, /// <summary>
/// 中断模式 允许自动关闭一下获得任务释放CPU资源
/// </summary>
BreakModel, /// <summary>
/// 睡眠模式 允许将活动任务设置为睡眠状态是否CPU资源
/// </summary>
SleepModel
}
管理模式枚举
public virtual void CreatParallelTask(Dictionary<Thread, object> list)
{
Action act = new Action(() =>
{
list.ToList().ForEach(a => a.Key.Priority = ThreadPriority.Lowest);
foreach (var item in list)
{
item.Key.Start(item.Value);
//break;
}
});
System.Threading.Tasks.ParallelOptions options = new System.Threading.Tasks.ParallelOptions();
options.MaxDegreeOfParallelism =list.Count ;
System.Threading.Tasks.Parallel.Invoke(options, new Action[] { act });
}
创建任务
创建任务也没什么比较难懂东西,就是把任务集合中的任务先用Action封装成方法 然后用System.Threading.Tasks.Parallel.Invoke 方法尽可能并行执行提供的每个操作。
后面这个控制并执行就有点复杂了,先看一下代码:
public virtual void CpuManagement(Dictionary<Thread, object> task, float cpuUpper, CpuManagementModelEnum cm)
{
Console.WindowWidth = ;
Thread t = new Thread(() =>
{
float avgCpu = ;
PerformanceCounter[] counters = new PerformanceCounter[System.Environment.ProcessorCount];
for (int i = ; i < counters.Length; i++)
{
counters[i] = new PerformanceCounter("Processor", "% Processor Time", i.ToString());
} while (true)
{
avgCpu = ;
for (int i = ; i < counters.Length; i++)
{
float f = counters[i].NextValue();
avgCpu += f;
}
avgCpu = avgCpu / counters.Length; if (avgCpu >= cpuUpper)
{
Console.Write("Sleep CPU-AVG: "
+ Math.Round(avgCpu, ).ToString().PadLeft(, ' ') + "%"
+ " CoreCount:" + counters.Length
+ " BusyThreadCount:" + task.Count(a => a.Key.ThreadState == System.Threading.ThreadState.Running).ToString()
+ " ThreadTotalCount:" + task.Count);
foreach (var item in task)
{
if (item.Key.ThreadState != System.Threading.ThreadState.Suspended)
{
item.Key.Suspend();
switch (cm)
{
case CpuManagementModelEnum.None:
break;
case CpuManagementModelEnum.BreakModel:
break;
case CpuManagementModelEnum.SleepModel:
System.Threading.Thread.Sleep();
break;
default:
break;
}
}
}
Console.Write(" Wait... \r\n");
}
else
{
Console.Write("Run CPU-AVG: " + Math.Round(avgCpu, ).ToString().PadLeft(, ' ') + "%"
+ " CoreCount:" + counters.Length
+ " BusyThreadCount:" + task.Count(a => a.Key.ThreadState == System.Threading.ThreadState.Running).ToString()
+ " ThreadTotalCount:" + task.Count);
foreach (var item in task)
{
if (item.Key.ThreadState == System.Threading.ThreadState.Suspended)
{
item.Key.Resume();
switch (cm)
{
case CpuManagementModelEnum.None:
break;
case CpuManagementModelEnum.BreakModel:
break;
case CpuManagementModelEnum.SleepModel:
System.Threading.Thread.Sleep();
break;
default:
break;
}
}
}
Console.Write(" Buy... \r\n");
}
System.Threading.Thread.Sleep();
}
});
t.Priority = ThreadPriority.Highest;
t.Start();
}
CPU管理执行任务
这里面主要就是做两个事:一、是对整体CPU资源被占用超过一个基数的时候要对现有的任务管理集合中的任务进行挂起操作;
二、是对整体CPU资源被占用小于定的基数的时候 继续已挂起的线程;
这个方法的第二个参数就是咱们想设定的CPU资源被占用到多大的基数上限开始使这时候运行的程序挂起部分线程释放资源,比如你想让CPU保持在90%左右,留有一部分空间来处理别的进程突发占用的情况或者别的情况这要视场景而定了。
在这执行任务当中用到两个已经过时的API:
System.Threading.Thread中的Suspend和Resume ,看到msdn上的有个警告
大概是说如果使用挂起的话当这个线程正好持有锁的话这个AppDomain的其他线程很可能都被堵死了,或者是在挂起一个线程在执行一个类的构造函数这个AppDomin其他线程使用这个类会受阻。很容易发生死锁现象。

可能主要就是这个原因吧!有知道比较详细的朋友可以留言告诉我,大家互相学习嘛。。。
这两个方法上倒是写了一些:
关于解决死锁问题直接使用 System.Threading.Monitor 会更好,这里主要介绍CPU多核控速问题,所以上面代码就不修改了。这个关于多线程上的五种基本问题之一的 死锁 在这就不详细讨论了。
下面咱们再回头看一下 这种受控制的情况下如何在应用程序中实现:
/// <summary>
/// 受控的并行执行
/// </summary>
/// <param name="icmt"></param>
public void Test2(ICpuManagementTask icmt)
{
AutomaticCpuManagement CPU = new AutomaticCpuManagement(); Dictionary<Thread, object> task = new Dictionary<Thread, object>();
task.Add(new Thread(new ParameterizedThreadStart(icmt.DoWork)), System.DateTime.Now);
task.Add(new Thread(new ParameterizedThreadStart(icmt.DoWork)), System.DateTime.Now.AddSeconds());
task.Add(new Thread(new ParameterizedThreadStart(icmt.DoWork)), System.DateTime.Now.AddSeconds());
task.Add(new Thread(new ParameterizedThreadStart(icmt.DoWork)), System.DateTime.Now.AddSeconds()); CPU.CreatParallelTask(task);
CPU.CpuManagement(task, 90F, AutomaticCpuManagement.CpuManagementModelEnum.BreakModel);
}
受控制实现
启动调试 的两条代码:
static void Main(string[] args)
{
ICpuManagementTask icmt;
ApplictionClass app = new ApplictionClass(out icmt); // app.Test1(icmt);
//Console.ReadKey(); app.Test2(icmt);
Console.ReadKey();
}
启动调试
分别调试两种方式进行观察就得到开头所看到的占用硬件资源不同的情况了。
CPU多核控速的更多相关文章
- paip.提升性能---mysql 优化cpu多核以及lan性能的关系.
paip.提升性能---mysql 优化cpu多核以及lan性能的关系. 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:/ ...
- R语言的并行运算(CPU多核)
通常R语言运行都是在CPU单个核上的单线程程序.有时我们会有需求对一个向量里的元素应用相同的函数,最终再将结果合并,并行计算可以大幅节约时间. 为了支持R的并行运算, parallel包已经被纳入了R ...
- CPU 多核指令 —— WFE 原理【原创】
转自:http://tinylab.org/arm-wfe/ Zhang Binghua 创作于 2020/05/19 打赏 微信公众号 知识星球 关注 @泰晓科技 与数千位一线 Linux 工程 ...
- Msbuild利用cpu多核加速
msbuild /t:Rebuild /p:Configuration=Release /m /m 自动检测cpu数量启动对应数量进程
- 充分利用CPU多核的处理能力 innodb_read_io_threads和innodb_write_io_threads
https://book.2cto.com/201402/40300.html 在MySQL5.1.X版本中,innodb_file_io_threads参数默认是4,该参数在Linux系统上是不可更 ...
- Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity) 转
硬件中断发生频繁,是件很消耗 CPU 资源的事情,在多核 CPU 条件下如果有办法把大量硬件中断分配给不同的 CPU (core) 处理显然能很好的平衡性能.现在的服务器上动不动就是多 CPU 多核. ...
- 多CPU,多核,多进程,多线程
当面临这些问题的时候,有两个关键词无法绕开,那就是并行和并发. 首先,要先了解几个概念: 1.进程是程序的一次执行. 2.进程是资源分配的基本单位(调度单位). 3.一个进程可以包括多个线程. 4.在 ...
- 软件设计师考试计算机系统知识——CPU
第一章: 计算机系统知识 1.1.1计算机系统硬件的基本组成 运算器.控制器.存储器.输入设备.输出设备 1.1.2 中央处理器 ①CPU的功能: a.程序控制:CPU通过执行指令来控制程序执行的顺序 ...
- cpu 性能
我们平时使用的CPU利用率方法是极具误导性的,并且一年更甚一年.那么什么是CPU利用率?是你的CPU到底有多忙,是像“% CPU”这样到处在用的指标所显示的那样吗? 在top命令里,你看到90%的CP ...
随机推荐
- shell脚本一键安装mysql5.7.x(免安装版)
使用脚本一键安装mysql5.7.x,初始化数据库,启动数据库---- mysql版本:源码mysql5.7.10 linux版本:centos6.5 x86_64 #!/bin/bash GROUP ...
- Ruby开发环境
Windows上Ruby开发环境的配置 最近公司项目上有需要,需要开发一个puppet的自动化工具,这个工具需要操作存储设备上的各种资源,而鉴于puppet不是善于完成这个任务的首选语言,于是我们 ...
- C#7模范和实践
C# 7 中的模范和实践 原文地址:https://www.infoq.com/articles/Patterns-Practices-CSharp-7 关键点 遵循 .NET Framework ...
- JavaScript函数实现鼠标指向后带图片的提示效果
转载:http://www.cnblogs.com/jack86514/archive/2009/04/01/1427584.html 当我们在写一个网页程序的时候,很多方法可以提供页面的动态显示,从 ...
- matlab 编程的细节问题
1. reshape 对元素的操作 使用单一维度对矩阵进行操作时,矩阵是逐列地进行编号的(如下矩阵中的 4, 5, 6,分别在矩阵 A 的第 4, 5, 6 索引处,而不是以行进行排序的 2,5,8 ...
- WPF 通过位处理合并图片
原文:WPF 通过位处理合并图片 本文告诉大家,在使用 WPF 合并两张图片的处理,可以使用像素之间的与或和异或的方式,对三个颜色的通道进行处理. 先给大家看一下软件的界面 这就是通过将左边的两张图片 ...
- C#步骤控件
C#开发step步骤条控件 现在很多的javascript控件,非常的不错,其中step就是一个,如下图所示: 那么如何用C#来实现一个step控件呢? 先定义一个StepEntity类来存储步骤 ...
- FontAwesome 图标
FontAwesome 图标 前言 FontAwesome 大家都不陌生,精美的图标,出现在各式各样的网页中.最近在做 Windows Forms 应用程序,要求美观,就想能不能把 FontAweso ...
- 简明Python3教程 11.数据结构
简介 数据结构基本上就是 – 可以将一些数据结合到一起的结构,换言之用于存储一组相关的数据. python拥有4种内建数据结构 – 列表,元组(tuple),字典和集合. 我们将看到如何它们,它们又是 ...
- ASP.NET Core 动作结果 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 动作结果 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 动作结果 前面的章节中,我们一直使用简单的 C# 类作为控制器. 虽 ...