把 CPU “玩”起来
前言
从开始学习编程之后,就渐渐痴迷于技术,平时遇到购书满减活动时就忍不住买一堆书。前两天闲着无聊,翻开了去年买的《编程之美》,目录里的“让 CPU 占用率听你指挥”吸引力我的眼球。这一年来捣鼓数据挖掘和机器学习,总会关注代码运行效率,偶尔会思考如何提高 CPU、GPU 的利用率。于是马上翻开了这一节。
让 CPU 利用率听你指挥
翻开后是一道编程题(3星,需要查阅一些资料,在60分钟内完成)
写一个程序,让用户来决定 Windows 任务管理器(Task Manager)的 CPU 占用率。程序设计的越精简越好,语言不限。例如,可实现下面三种情况:
- CPU 和占用率固定在50%,为一条直线
- CPU 的占用率为一条直线,具体占用率由命令行参数决定(参数范围 1~100)
- CPU 的占用率状态是一条正弦曲线
怎么实现呢
稍微想了想,如果想让 CPU 跑满,写一个死循环就好了,让 CPU 一直处于运行状态,那 50% 的利用率要怎么实现呢?一半时间运行一半时间休息,emmmmm。。休息。。突然想到了多线程里常用到的 sleep。接着往下看,确实是使用 sleep。
那就写写代码吧
while True:
for i in range(7200000):
pass
time.sleep(0.01)
这里稍微解释下为什么是 7200000,以及为什么睡眠 0.01s(10ms)。
笔记本的 CPU 是 1.8Ghz,每秒运行次数大概为 1.8 * 10^9 次,假设 CPU 每个时钟周期可以执行两条代码,然后对于一段 for 循环代码,转换成汇编如下
next:
mov eax, dword ptr[i] ; i放入寄存器
add eax, 1 ; 寄存器+1
mov dword ptr [i], eax ; 寄存器赋回i
cmp eax, dword ptr [i] ; 比较i和n
j1 next ; i小于n时重复循环
即5条代码,所以,1S 内循环次数为 1.8 * 10^9 * 2 / 5 = 720000000。而睡眠 10ms 是因为接近 Windows 的调度时间片。
运行了一下,只是稳定在 30% 左右,暂时先不调整循环次数,接着往后看。
可以看出来,这样设置利用率很麻烦,那有没有什么方法可以快点设置呢?
重新看看上面这段代码, 7200000 次循环花费的时间大约为 10ms,那意思就是 CPU 运行 10ms 然后再休息 10ms,再运行 10ms 再休息 10ms,接着运行 10ms 然后再休息 10ms ······ 想必肯定看出来什么了吧,我们只需要设置 CPU 运行多少时间就好了!于是可以写出下面代码
busyTime = 0.01
while True:
startTime = time.clock()
while((time.clock() - startTime) <= busyTime):
pass
time.sleep(busyTime)
运行一下,跟刚刚差不太多,稳定在 30% 左右
正弦函数
这时候,我们也可以很容易就写出跑成正弦函数图像的代码了,不断改变运行与空闲的时间比就好了。
import time
import mathimport affinity
from multiprocessing import Process, cpu_count def exec_fun():
SAMPLING_COUNT = 200 # 抽样点数量
PI = math.pi # pi
TOTAL_AMPLITUDE = 300 # 每个抽样点对应时间片
busySpan = [] amplitude = TOTAL_AMPLITUDE / 2
radianIncrement = 2.0 / SAMPLING_COUNT
radian = 0.0
for i in range(SAMPLING_COUNT):
busySpan.append((amplitude + math.sin(PI * radian) * amplitude) / 1000.0)
radian += radianIncrement
# print(busySpan[i], TOTAL_AMPLITUDE - busySpan[i]) j = 0
while True:
startTime = time.clock()
# print(startTime)
while ((time.clock() - startTime) <= busySpan[j]):
pass
# print('sleep')
time.sleep(0.3 - busySpan[j])
j = (j + 1) % SAMPLING_COUNT exec_fun()
运行一下。emmmmmmmmmmmm。。。。等一下,不对啊,怎么不是正弦函数形状呢?
这跟说好的好像不太一样啊。是不是因为用的是 python,跑的本来就慢的原因?那试试 C++ 吧
#include<stdlib.h>
#include<Windows.h>
#include<math.h> const int SAMPLING_COUNT = ;
const double PI = 3.1415926535;
const int TOTAL_AMPLITUDE = ; int main()
{
DWORD busySpan[SAMPLING_COUNT];
int amplitude = TOTAL_AMPLITUDE / ;
double radian = 0.0;
double radianIncrement = 2.0 / (double)SAMPLING_COUNT;
for (int i = ; i < SAMPLING_COUNT; i++) {
busySpan[i] = (DWORD)(amplitude + sin(radian * PI) * amplitude);
radian += radianIncrement;
printf("%d\t%d\n", busySpan[i], TOTAL_AMPLITUDE - busySpan[i]);
}
DWORD startTime = ;
for (int j = ;; j = (j + ) % SAMPLING_COUNT) {
startTime = GetTickCount();
while ((GetTickCount() - startTime) <= busySpan[j]);
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
return ;
}
再运行一下,它怎么还是这样???
于是乎捣鼓了 2 个小时。。。
……
……
……
后来仔细想了想,CPU 是 4 核 8 处理器的,不会是任务分摊到了几个处理器上了吧?于是查了查如何把当前进程放在一个处理器上执行。
if __name__ == "__main__":
p = Process(target=exec_fun)
p.start()
pid = p.pid
print(affinity.get_process_affinity_mask(pid))
affinity.set_process_affinity_mask(pid, )
运行一下,好的,它成了!!!
顺便解决下上面C++的代码,在 main() 函数最开始加入下面代码
SetThreadAffinityMask(GetCurrentThread(), );
小节
好久没有这样子捣鼓过东西了,想想上次做操作系统课设的时候,要获取系统的信息,当时只是为了完成任务就没有去深究一些东西,这次捣鼓了 CPU 的利用率控制之后,对进程、CPU 以及 python 的多线程等知识又多了一点了解。感觉技术还是需要沉下心来才能学得好。
把 CPU “玩”起来的更多相关文章
- C#正则表达式引发的CPU跑高问题以及解决方法
3月23日(周日)下午16:30左右,博客园主站负载均衡中的2台Web服务器CPU玩起了爬楼梯的游戏(见上图),一直爬到了接近100%.发现这个状况后,我们立即将这2台阿里云临时磁盘云服务器从负载均衡 ...
- 横跨十年CPU架构回顾
http://cpu.zol.com.cn/209/2092791_all.html#p2092791 本文导航 第1页:K7架构 打开AMD崛起大门的钥匙 第2页:玩破解 K7时代便已经拥有 第3页 ...
- Acer4315笔记本CPU升级
终于有时间升级一下不怎么用的旧笔记本Acer4315了.在计划升级前了解了一下,芯片组是GL960,支持可升级的CPU有: CM560 CM570 T1600 T1700 T2310 T2330 T2 ...
- STM32 串口功能 库函数 详解和DMA 串口高级运用(转载)
数据传输时要从支持那些相关的标准?传输的速度?什么时候开始?什么时候结束?传输的内容?怎样防止通信出错?数据量大的时候怎么弄?硬件怎么连接出发,当然对于stm32还要熟悉库函数的功能 具起来rs232 ...
- Linux kernel parameter command line设置
现在CPU2核以上比较普遍了,平时用linux上上网可能用不着双核甚至4核,大部分发行版内核都启用了CPU_HOTPLUG,到/sys/devices/system/cpu下可以看到文件夹cpu0.c ...
- 教你从头到尾利用DQN自动玩flappy bird(全程命令提示,GPU+CPU版)【转】
转自:http://blog.csdn.net/v_JULY_v/article/details/52810219?locationNum=3&fps=1 目录(?)[-] 教你从头到尾利用D ...
- 玩转CPU运行曲线
Leaf 是不是从来没有想过看看cpu运行曲线啊骚年?顶多也就仅仅是看看cpu利用率,吓自己一跳后感觉关闭几个不该打开的程序~ 然而问题来了,微软公司要让你绘制cpu运行曲线啊!!不仅是固定的直线,还 ...
- 深入理解 Linux Cgroup 系列(二):玩转 CPU
原文链接:深入理解 Linux Cgroup 系列(二):玩转 CPU 上篇文章主要介绍了 cgroup 的一些基本概念,包括其在 CentOS 系统中的默认设置和控制工具,并以 CPU 为例阐述 c ...
- [转帖]海思大佬称华为CPU同频追平AMD 注水吹嘘玩文字游戏?
海思大佬称华为CPU同频追平AMD 注水吹嘘玩文字游戏? https://t.cj.sina.com.cn/articles/view/6635931736/18b88485800100cz4h?fr ...
随机推荐
- linux并口纵览
因为我们期望大部分读者以所谓的"个人计算机"的形式使用一个 x86 平台, 我们觉得值 得解释一下 PC 并口如何设计的. 并口是在个人计算机上运行数字 I/O 例子代码的外设 接 ...
- 2018百度之星资格赛A B F
A.调查问卷 度度熊为了完成毕业论文,需要收集一些数据来支撑他的论据,于是设计了一份包含 mm 个问题的调查问卷,每个问题只有 'A' 和 'B' 两种选项. 将问卷散发出去之后,度度熊收到了 nn ...
- Java实现简单的学生成绩管理系统
ScoreInformation.java import java.util.Scanner; class ScoreInformation { private String stunumber ...
- SQLAlchemy的增删改查 一对多 多对多
Models只是配置和使用比较简单,因为是Django自带的ORM框架,所以兼容性不行,所以出现了SQLAlchemy,SQLAlchemy是比较全面的ORM框架,它可以在任何使用SQL查询时使用 以 ...
- hadoop中 namenode的持久化
一.为什么namenode持久化 namenode通过内存存储hdfs集群的元数据(目录结构 文件信息 块对应关系),如果内存出现问题,那么会数据丢失,需要通过持久化,把内存中的数据定期的存储在硬盘中 ...
- PLsql下载官网下载地址
https://www.allroundautomations.com/registered/plsqldev.html
- [Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串
本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学V ...
- nginx负载均衡的相关配置
一台nginx的负载均衡服务器(172.25.254.131) 两台安装httpd作为web端 一.准备工作 1.1 安装nginx yum -y install gcc openssl-devel ...
- 【题解】Comet OJ Round 70 简要题解
[题解]Comet OJ Round 70 简要题解 A 将放在地上的书按照从小到大排序后,问题的本质就变成了合并两个序列使得字典序最小.可以直接模拟归并排序.直接用循环和std::merge实现这个 ...
- java数据结构之常用排序算法
冒泡排序 private void maopao(int arr[]) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j &l ...