术语“CPU限制”和“I/O限制”是什么意思?
当前回答
另一种表达相同想法的方式是:
如果加速CPU并没有加速你的程序,它可能是I/O受限的。 如果加速I/O(例如使用更快的磁盘)没有帮助,那么您的程序可能是CPU受限的。
(我使用“可能是”是因为你需要考虑其他资源。内存就是一个例子。)
其他回答
CPU限制是指进程的速度受CPU速度的限制。对一小组数字执行计算的任务,例如乘小矩阵,可能会受到CPU的限制。
I/O约束是指进程的速度受I/O子系统的速度限制。处理来自磁盘的数据的任务(例如,计算文件中的行数)可能受到I/O限制。
内存限制是指进程进程的速度受可用内存数量和内存访问速度的限制。处理大量内存内数据的任务,例如乘法大型矩阵,很可能是memory Bound。
缓存约束是指进程进程受可用缓存数量和速度限制的速率。如果一个任务处理的数据超过了缓存的容量,那么它就会被缓存绑定。
I/O绑定比内存绑定慢,缓存绑定比CPU绑定慢。
I/O受限的解决方案不一定是获得更多内存。在某些情况下,访问算法可以围绕I/O、内存或缓存限制进行设计。参见缓存无关算法。
IO绑定进程:花更多的时间做IO比计算,有很多 短CPU突发。 CPU绑定进程:花费更多的时间进行计算,很少有很长时间的CPU爆发
看看微软怎么说。
The core of async programming is the Task and Task objects, which model asynchronous operations. They are supported by the async and await keywords. The model is fairly simple in most cases: For I/O-bound code, you await an operation which returns a Task or Task inside of an async method. For CPU-bound code, you await an operation which is started on a background thread with the Task.Run method. The await keyword is where the magic happens. It yields control to the caller of the method that performed await, and it ultimately allows a UI to be responsive or a service to be elastic.
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);
};
Examples above showed how you can use async and await for I/O-bound and CPU-bound work. It's key that you can identify when a job you need to do is I/O-bound or CPU-bound, because it can greatly affect the performance of your code and could potentially lead to misusing certain constructs. Here are two questions you should ask before you write any code: Will your code be "waiting" for something, such as data from a database? If your answer is "yes", then your work is I/O-bound. Will your code be performing a very expensive computation? If you answered "yes", then your work is CPU-bound. If the work you have is I/O-bound, use async and await without Task.Run. You should not use the Task Parallel Library. The reason for this is outlined in the Async in Depth article. If the work you have is CPU-bound and you care about responsiveness, use async and await but spawn the work off on another thread with Task.Run. If the work is appropriate for concurrency and parallelism, you should also consider using the Task Parallel Library.
当一个应用程序在执行期间的算术/逻辑/浮点(A/L/FP)性能大部分接近处理器的理论峰值性能(数据由制造商提供,由处理器的特性决定:核数、频率、寄存器、alu、fpu等)时,它就被cpu绑定了。
peek性能在实际应用中是很难实现的,并不是说不可能。大多数应用程序在不同的执行过程中访问内存,处理器在几个周期内不会执行A/L/FP操作。由于内存和处理器之间存在距离,这被称为冯·诺依曼限制。
If you want to be near the CPU peak-performance a strategy could be to try to reuse most of the data in the cache memory in order to avoid requiring data from the main memory. An algorithm that exploits this feature is the matrix-matrix multiplication (if both matrices can be stored in the cache memory). This happens because if the matrices are size n x n then you need to do about 2 n^3 operations using only 2 n^2 FP numbers of data. On the other hand matrix addition, for example, is a less CPU-bound or a more memory-bound application than the matrix multiplication since it requires only n^2 FLOPs with the same data.
下图显示了在Intel i5-9300H中使用简单的矩阵加法和矩阵乘法算法获得的FLOPs:
注意,正如预期的那样,矩阵乘法的性能要大于矩阵加法。可以通过运行这个存储库中的test/gemm和test/matadd来重现这些结果。
我建议你也去看看J. Dongarra关于这个效果的视频。
I/O限制是指完成计算所需的时间主要由等待输入/输出操作完成的时间决定的一种情况。
这与受CPU限制的任务相反。当请求数据的速度比消耗数据的速度慢时,或者换句话说,花费在请求数据上的时间比处理数据的时间多时,就会出现这种情况。