#1 楼
这非常直观:如果CPU速度更快,程序运行速度就会更快,即受CPU限制,也就是说,程序大部分时间仅用于CPU(进行计算)。计算π的新数字的程序通常受CPU限制,只是对数字进行运算。
如果I / O子系统更快,则程序运行速度会更快,因此受I / O限制。确切的I / O系统意味着什么?我通常将其与磁盘相关联,但是当然,一般而言,联网或通信也很常见。通过大文件查找某些数据的程序可能会成为I / O绑定,因为瓶颈是随后从磁盘读取数据(实际上,此示例如今可能已经过时,具有数百MB / s的速度)。从SSD进入)。
评论
这如何与理解移动设备上的HTTP通信联系在一起?我已经看到使用java.nio操作会导致CPU使用率激增。
– IgorGanapolsky
18年6月28日在19:49
I / O是“输入/输出”。
–车同志
19年5月30日在4:40
#2 楼
CPU绑定是指进程进行的速率受CPU速度的限制。在少量数字上执行计算的任务(例如,将小的矩阵相乘)很可能受CPU限制。I / O绑定意味着进程的执行速度受到速度的限制I / O子系统的名称。处理磁盘数据的任务(例如,计算文件中的行数)很可能受I / O约束。
内存约束意味着进程的执行速度受到可用内存量以及该内存访问的速度。处理大量内存数据(例如,乘以大型矩阵)的任务很可能是“内存绑定”。
高速缓存绑定是指进程进度受可用高速缓存的数量和速度限制的速率。
I / O Bound的速度将比Memory Bound的速度慢,而Cache Bound的速度将比CPU Bound的速度慢。
/>
解决I / O绑定的方法不一定获得更多的内存。在某些情况下,可以围绕I / O,内存或缓存限制来设计访问算法。请参阅缓存遗忘算法。
#3 楼
多线程在这个答案中,我将研究一种区分CPU和IO受限工作的重要用例:编写多线程代码时。
RAM I / O绑定示例:向量求和
考虑一个程序,该程序将单个向量的所有值求和:
#define SIZE 1000000000
unsigned int is[SIZE];
unsigned int sum = 0;
size_t i = 0;
for (i = 0; i < SIZE; i++)
/* Each one of those requires a RAM access! */
sum += is[i]
通过在每个现代内核上均等地拆分数组来并行化它,在常见的现代台式机上用途有限。
例如,在我的Ubuntu 19.04上,带有CPU的Lenovo ThinkPad P51笔记本电脑:Intel Core i7-7820HQ CPU(4核/ 8线程),RAM:2x Samsung M471A2K43BB1-CRC(2x 16GiB)我得到这样的结果:
绘制数据。
请注意,运行之间存在很大差异。但是由于我已经在8GiB上了,所以我无法进一步增加阵列大小,并且我现在不打算进行多次运行的统计信息。但是,在执行许多手动运行之后,这似乎是一种典型的运行。
基准代码:
图中使用的POSIX C
pthread
源代码。这是一个产生相似结果的C ++版本。
绘图脚本
我不知道足够的计算机体系结构来完全解释曲线的形状,但有一点很清楚:由于我使用了我的所有8个线程,因此计算速度不会像天真预期的那样快8倍!出于某种原因,2和3个线程是最佳选择,添加更多线程只会使事情变慢。
将其与CPU限制的工作进行比较,实际上速度快了8倍:“真实”,“用户”和“实际” “ sys”是指time(1)的输出吗?
所有处理器共享链接到RAM的单个内存总线的原因是:
CPU 1 --\ Bus +-----+
CPU 2 ---\__________| RAM |
... ---/ +-----+
CPU N --/
所以内存总线很快成为瓶颈,而不是CPU。
发生这种情况是因为在2016年的硬件中,两个数相加需要一个CPU周期,而内存读取大约需要100个CPU周期。
因此输入数据的每个字节完成的CPU工作量太小,并且我们将其称为IO绑定过程。
进一步加速该计算的唯一方法是使用新的存储硬件(例如,内存)来加速单个内存的访问。多通道内存。例如,升级到更快的CPU时钟将不是很有用。
其他示例
矩阵乘法在RAM和CPU上受CPU限制。 GPU。输入包含:
2 * N**2
数字,但是:
N ** 3
已经完成乘法运算,对于实际的大N来说,并行化是值得的。
这就是为什么存在以下类似的并行CPU矩阵乘法库的原因:
http://www.netlib.org/scalapack/pblas_qref.html
http://icl.cs.utk.edu / magma / software /
缓存的使用对实现速度有很大的影响。例如,请参见该教学GPU的比较示例。
另请参见:
GPU为什么矩阵乘法比CPU快?
与GPU的LAPACK函数等效的BLAS
网络化是受IO约束的典型示例。
即使当我们发送单个字节的数据时,仍然需要很长时间才能到达目的地。
对小型网络请求(如HTTP请求)进行并行处理可以带来巨大的性能提升。
如果网络已经满负荷运行(例如下载torrent),并行化仍会增加延迟(例如,您可以在“一次”)。
一个虚假的C ++ CPU绑定操作,需要一个数字并对其进行大量运算:
序列号
parallel
EEMBC著名的Coremark基准测试明确检查了一系列问题的扩展程度。我在以下位置对此发表了评论:https://cirosantilli.com/linux-kernel-module-cheat/#coremark示例结果清除显示:
Workload Name (iter/s) (iter/s) Scaling
----------------------------------------------- ---------- ---------- ----------
cjpeg-rose7-preset 526.32 178.57 2.95
core 7.39 2.16 3.42
linear_alg-mid-100x100-sp 684.93 238.10 2.88
loops-all-mid-10k-sp 27.65 7.80 3.54
nnet_test 32.79 10.57 3.10
parser-125k 71.43 25.00 2.86
radix2-big-64k 2320.19 623.44 3.72
sha-test 555.56 227.27 2.44
zip-test 363.64 166.67 2.18
MARK RESULTS TABLE
Mark Name MultiCore SingleCore Scaling
----------------------------------------------- ---------- ---------- ----------
CoreMark-PRO 18743.79 6306.76 2.97
C ++程序的链接可以在一定程度上并行化:链接时gcc可以使用多个内核吗?
如何找出是否受CPU或IO约束
无-RAM IO像磁盘,网络一样绑定:
ps aux
,然后检查CPU% / 100 < n threads
。如果是,则表示您受IO约束,例如阻塞read
只是在等待数据,而调度程序正在跳过该过程。然后使用其他工具,例如sudo iotop
来确定到底是哪个IO。或者,如果执行速度很快,并且对线程数进行参数化,则可以很容易地从
time
看到随着线程数的增加性能会提高。对于CPU限制的工作:time(1)输出中的“ real”,“ user”和“ sys”是什么意思?RAM-IO限制:更难说,因为RAM等待时间包含在
CPU%
中测量,另请参阅:如何检查应用是否受CPU约束或受内存约束?
https://askubuntu.com/questions/1540/how-can-i-find如果进程是CPU内存或磁盘绑定
某些选项:
英特尔顾问屋顶线(非免费):https: //software.intel.com/zh-cn/articles/intel-advisor-roofline(存档)“ Roofline图表是与硬件限制(包括内存带宽和计算峰值)相关的应用程序性能的直观表示。”
GPU
首次传输输入时,GPU出现IO瓶颈数据从常规CPU可读RAM传输到GPU。
因此,GPU只能比CPU绑定应用程序的CPU更好。
一旦将数据传输到GPU,它就可以更快地对这些字节进行操作超过了CPU,因为GPU:
具有比大多数CPU系统更多的数据本地化功能,因此某些内核的数据访问速度比其他内核要快
利用数据并行性并通过跳过任何未准备就绪的数据来牺牲延迟
由于GPU必须对大型并行输入数据进行操作,因此最好跳到可能可用的下一个数据,而不是等待当前数据可用并阻塞所有其他数据像CPU这样的操作通常会执行
因此,如果您的应用程序可以高度并行化,那么GPU可以比CPU更快,
可以高度并行化:可以将不同的数据块同时彼此分开处理
每个输入字节需要足够多的操作(不同于矢量加法,该操作仅对每个字节进行一次加法)
有大量输入字节
/>
这些设计选择最初是针对3D渲染的应用,其主要步骤如下:
顶点着色器:将一堆1x4向量乘以4x4矩阵
片段着色器:计算像素的每个像素的颜色基于三角形相对位置的三角形
,因此我们得出结论,这些应用程序受CPU限制。
随着可编程GPGPU的问世,我们可以观察到一些GPGPU应用程序CPU绑定操作的示例:
使用GLSL着色器进行图像处理?
本地图像处理操作(例如模糊滤镜)本质上是高度并行的。 />
是否可以以每秒60次的速度从点数据构建热图?
如果绘制的函数足够复杂,则可以绘制热图图。
https://www.youtube.com/watch?v=fE0P6H8eK4IJesúsMartínBerlanga的“实时流体动力学:CPU与GPU”
解决偏微分方程,例如流体动力学的Navier Stokes方程:
本质上是高度平行的,因为每个点仅与它们的邻居相互作用
每字节往往有足够的操作
另请参见:
为什么我们仍在使用CPU而不是GPU?
GPU有什么缺点?
/>https://www.youtube.com/watch?v=_cyVDoyI6NE“ CPU与GPU(有什么区别?)-Computerphile”
CPython全局解释器锁(GIL)
快速案例研究,我想指出一下Python全局解释器锁(GIL):什么是CPython中的全局解释器锁(GIL)?
此CPython实现细节阻止了多个Python线程有效地使用CPU绑定工作。 CPython文档说:
CPython实现细节:在CPython中,由于具有全局解释器锁,因此只有一个线程可以一次执行Python代码(即使某些面向性能的库可以克服此限制)。如果希望您的应用程序更好地利用多核计算机的计算资源,建议您使用
multiprocessing
或concurrent.futures.ProcessPoolExecutor
。但是,如果您想同时运行多个I / O绑定任务,则线程化仍然是一种合适的模型。因此,这里有一个示例,其中CPU绑定的内容不合适并且I / O绑定了是。
评论
伙计,你如何才能如此胜任并做出这样的写作?
– Mikayil Abdullayev
1月13日4:47
@MikayilAbdullayev谢谢!我倾向于只回答“重要问题”,在学习新的相关知识时,我会一遍又一遍地回到他们身上。
– Ciro Santilli郝海东冠状病六四事件法轮功
1月13日9:21
#4 楼
受CPU限制意味着程序受到CPU或中央处理器的瓶颈,而受I / O约束意味着程序受到I / O或输入/输出(例如对磁盘,网络等的读写)的瓶颈。 />通常,在优化计算机程序时,人们试图找出瓶颈并消除它。知道您的程序受CPU限制是有帮助的,这样就不会不必要地优化其他内容。
[并且通过“瓶颈”,我的意思是使您的程序运行得比其他程序慢。 。]
#5 楼
表示相同想法的另一种方法:如果加速CPU不能加速程序,则可能是I / O绑定。
如果加速I / O(例如,使用更快的磁盘)无济于事,您的程序可能与CPU绑定。
(我使用“可能是”是因为您需要考虑其他资源。内存是一个示例。)
#6 楼
当程序正在等待I / O(即磁盘读/写或网络读/写等)时,即使程序已停止,CPU也可以自由执行其他任务。程序的速度主要取决于IO发生的速度,如果要加快IO的速度,则需要加快I / O的速度。如果程序正在运行很多程序指令,而不是等待I / O,则被认为与CPU绑定。加速CPU将使程序运行更快。
在两种情况下,加速程序的关键可能不是加速硬件,而是优化程序以减少IO量。或需要的CPU,或者执行I / O,同时还占用大量CPU资源。
#7 楼
IO绑定进程:花在执行IO上的时间比计算要多,有很多短CPU突发次数。
CPU绑定进程:花更多的时间在计算上,很少的很长CPU突发时间
#8 楼
I / O界限是指一种条件,其中完成计算所需的时间主要由等待输入/输出操作完成所花费的时间确定。这与受CPU约束的任务相反。当请求数据的速率比消耗数据的速率慢,或者换句话说,花费数据的时间多于处理数据的时间时,就会出现这种情况。
#9 楼
当执行过程中的算术/逻辑/浮点(A / L / FP)性能在大多数情况下接近处理器的理论峰值性能(制造商提供的数据,并由处理器的特性确定)时,应用程序受CPU限制。处理器:内核的数量,频率,寄存器,ALU,FPU等)。在实时应用中很难达到惊人的性能,这并不是说不可能。大多数应用程序在执行的不同部分访问内存,并且处理器在几个周期内未执行A / L / FP操作。由于内存和处理器之间存在距离,因此称为Von Neumann限制。
如果您想要接近CPU的峰值性能,则可以尝试重用大部分数据为了避免需要来自主存储器的数据,在高速缓冲存储器中存储数据。利用此功能的一种算法是矩阵矩阵乘法(如果两个矩阵都可以存储在高速缓存中)。发生这种情况的原因是,如果矩阵的大小为
n x n
,那么您只需要使用2 n^3
FP数据数就可以执行2 n^2
运算。另一方面,例如,与矩阵乘法相比,矩阵加法是CPU较少的应用程序或内存较多的应用程序,因为它仅需要n^2
个具有相同数据的FLOP。在下图中使用朴素算法在Intel i5-9300H中进行矩阵加法和矩阵乘法的FLOP显示如下:
请注意,矩阵乘法大于矩阵加法。通过运行此存储库中可用的
test/gemm
和test/matadd
可以复制这些结果。我还建议您观看J. Dongarra提供的有关此效果的视频。
#10 楼
看看微软怎么说。异步编程的核心是Task和Task对象,它们对异步操作进行建模。它们由async和
await关键字支持。该模型在大多数情况下非常简单:
对于受I / O约束的代码,您需要等待一个操作,该操作将在异步方法内部返回Task或
Task。
对于受CPU约束的代码,您需要等待通过Task.Run方法在
后台线程上启动的操作。
await关键字是神奇的地方。它对等待执行的方法的
调用者产生控制,最终允许
UI响应或服务具有弹性。
I / O绑定示例:从Web服务下载数据
private readonly HttpClient _httpClient = new HttpClient();
downloadButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI as the request
// from the web service is happening.
//
// The UI thread is now free to perform other work.
var stringData = await _httpClient.GetStringAsync(URL);
DoSomethingWithData(stringData);
};
CPU绑定示例:执行游戏计算
private DamageResult CalculateDamageDone()
{
// Code omitted:
//
// Does an expensive calculation and returns
// the result of that calculation.
}
calculateButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI while CalculateDamageDone()
// performs its work. The UI thread is free to perform other work.
var damageResult = await Task.Run(() => CalculateDamageDone());
DisplayDamage(damageResult);
};
<上面的示例说明了如何使用async和等待来进行I / O绑定和CPU绑定的工作。当您需要做的工作是I / O绑定或CPU绑定时,您可以识别出
的关键,因为它会极大地影响代码的性能并有可能导致
滥用某些构造。
在编写任何代码之前,您应该问两个问题:
您的代码是否正在“等待”某些东西,例如来自<
如果您的回答是“是”,则您的工作受I / O约束。
您的代码是否会执行得非常好?计算昂贵吗?
如果回答“是”,则说明您的工作受CPU限制。
如果您拥有的工作受I / O限制,使用async并等待而无需
Task.Run。您不应该使用任务并行库。
这的原因在“深度异步”文章中有概述。
如果您的工作受CPU限制,并且您关心响应性,
使用异步并等待,但使用
Task.Run在另一个线程上完成工作。如果该工作适合于并发和并行性,
您还应该考虑使用任务并行库。
#11 楼
I / O绑定进程:-如果进程生命周期的大部分时间都处于I / O状态,则该进程就是AI / O绑定进程。示例:-calculator,internetexplorerCPU绑定进程:-如果进程寿命的大部分时间都花在cpu上,那么它就是cpu绑定进程。
评论
计算器将如何成为IO绑定进程?肯定是受CPU限制的。如果您的计算器大部分时间都因为访问网络或磁盘而受阻,那么我建议它出了点问题。
–rickerbh
2012年10月29日在21:16
我认为计算器示例很清楚:大多数情况下,它等待用户按下按钮,因此等待I / O。
–psp
2015年9月1日上午10:59
@psp是正确的,但是由于它的名称“ calculator”,因此从表面上看,该计算器示例仍然难以理解。这意味着该程序的主要目的是执行长时间的cpu计算,但是如果您在台式机上看一下计算器,这是一个非常简单的计算器,仅需完成纳秒级的计算即可。因此,大多数情况下,它在等待用户输入,即IO。
–校准器
18年8月14日在21:05
评论
如果内存有问题,请访问:stackoverflow.com/questions/11831844/…