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 ...
随机推荐
- 瀑布流的一些CSS实现方式
一个选择是用CSS3的多列columns,可以参考这篇文章.但这篇文章给的例子并不怎么好理解,我做了一些更改,在每个元素上加了序号.可以看到,多列布局是在每一列上依次排列元素的,第一列排完才开始排第二 ...
- python于lxml应用
首先下载lxml, http://www.lfd.uci.edu/~gohlke/pythonlibs/ ,然后加入引用 from lxml import _elementpath as DONTUS ...
- win10 uwp 线程池
原文:win10 uwp 线程池 如果大家有开发 WPF 或以前的程序,大概知道线程池不是 UWP 创造的,实际上在很多技术都用到线程池. 为什么需要线程池,他是什么?如何在 UWP 使用线程池,本文 ...
- 读取xml格式的字符串和上下文中的xml数据
1.读取xml格式的字符串 假设有一段下面的xml格式的字符串: <xml> <return_code><![CDATA[SUCCESS]]></re ...
- matlab 高阶(三)—— 插值(fft、)
1. FFT 插值 y = interpft(x,n) y = [0, .5, 1., 1.5, 2., 1.5, 1., .5, 0, -.5, -1, -1.5, -2., -1.5, -1., ...
- C++一个简单的手柄类模板
#ifndef HANDLE_H #define HANDLE_H #include "Animal.h" template <typename T> class Ha ...
- 阐述php(五岁以下儿童)
注意事项和使用功能
1.函数声明 <?php /** * function 函数名(參数1, 參数2.... ){ * 函数体; * 返回值; * } */ $sum = sum(3, 4); echo $sum; ...
- 微信公众平台消息接口开发(31)微信浏览器HTTP_USER_AGENT判断
微信公众平台开发 微信公众平台开发者 微信公众平台开发模式 微信浏览器 HTTP_USER_AGENT作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/archiv ...
- Multi-processor having shared memory, private cache memories, and invalidate queues having valid bits and flush bits for serializing transactions
Multi-processor systems are often implemented using a common system bus as the communication mechani ...
- A熟知SP.NET---WebForms UnobtrusiveValidationMode 必须“jquery”ScriptResourceMapping。
我相信,有过ASP.NET人们学习经验RequiredFieldValidator控制(验证非空控制)一定不会陌生,禁止控制输入定义的内容的作用(该属性InitialValue的值.属性默认值为空字符 ...