多线程是否意味着CPU使用率降低?

3
我有一个小的文件列表需要处理,这让我开始思考...
在C#中,我想使用TPL的Parallel.ForEach来利用现代多核CPU,但我的问题更多是假设性的;
实际上使用多线程是否意味着并行加载文件需要更长的时间(尽管可以使用尽可能多的CPU核心),而顺序加载每个文件则需要较少的CPU利用率?
换句话说:
多线程的重点是什么?并行执行更多任务,但速度更慢,还是专注于一项任务上使用所有计算资源?
6个回答

4
为了不增加延迟,并行计算程序通常每个内核只创建一个线程。非纯计算应用往往会添加更多的线程,以使可运行线程数等于内核数(其他线程处于I/O等待状态,不竞争CPU时间)。
现在,对于磁盘I/O受限的程序进行并行处理可能会导致性能下降;如果磁盘具有非零寻道时间,那么执行寻道操作所需的时间将会增加,实际读取数据的时间相应减少。这称为“磨损”或“抖动”。电梯式排序可以在一定程度上帮助解决问题,而真正的随机访问(如固态存储器)则可以更好地解决问题。
并行通常会增加总工作量,但仅当电池续航时间至关重要时才显得重要(考虑到其他组件(例如屏幕背光)使用的电量,完成更快通常仍然更加高效)。

鉴于现今的CPU可以按核心进行频率调节,因此为了“节省”电池电量而避免使用线程就变得更加没有意义了。 - Joseph Garvin
@JosephGarvin:我不相信支持每个核心的频率。而关闭次要核心的能力有利于单线程情况,从功耗角度来看非并行更有效--没有缓存冲突,不需要分割缓存,也没有同步逻辑。 - Ben Voigt
我知道每个核心的频率是被支持的,因为我的Thinkpad 410s可以做到这一点 :) 或者gnome频率监视器小程序有问题。我经常看到它显示1或2个核心被放大而其他核心没有。 - Joseph Garvin
@JosephGarvin:用的是什么CPU?我认为有一些核心是完全挂起的。如果所有活动核心都以相同的频率运行,我不会称之为每个核心的频率缩放。 - Ben Voigt

3

对于从磁盘加载文件,这可能会使事情变得更慢。操作系统试图将文件在磁盘上排列,以便每个文件只需要进行一次昂贵的磁盘查找。如果有很多线程读取很多文件,则线程之间会争用访问磁盘的权限,并且每次下一个线程获取轮换时,您将不得不重新定位到文件中的正确位置。

您可以使用正好两个线程。设置一个后台线程来加载所有文件,让另一个线程保持可用状态以执行其他任务,例如处理用户输入。 在C# winforms中,您可以使用BackgroundWorker控件轻松实现此操作。


同意第一部分,但第二部分只适用于“通常”。如果文件需要CPU大量处理,则可以使用更多线程,但每个磁盘只能使用1个线程进行读取。 - H H
@Henk - 如果它们需要的处理时间比阅读时间长,那么它们确实需要大量的处理。但即使在这种情况下,你几乎总是希望尽快按顺序读取文件,并使用生产者/消费者队列来处理处理,这样你就可以以最快的速度从一个文件中读取,并将工作项排队等待其他线程处理。 - Joel Coehoorn

3

您提出了多个问题,所以我将我的回答分成了多个部分:

  1. 多线程可能对加载速度没有影响,这取决于加载过程中的瓶颈是什么。如果您正在从磁盘或数据库中加载大量数据,则 I/O 可能是限制因素。另一方面,如果“加载”涉及使用某些数据进行大量 CPU 工作,则使用多线程可能会加快速度。

  2. 一般来说,您无法将“所有计算资源集中在一个任务上”。一些多核处理器具有超频单个核心的能力,但这种速度提升不等于通过使用多线程/多进程充分利用所有核心所能获得的潜在性能优势。换句话说,它是不对称的——如果您拥有一个 4 核心 1Ghz 的 CPU,它不会能够通过禁用其他核心来将单个核心超频到 4ghz。事实上,这就是行业首先采用多核心的原因——至少目前我们已经达到了单个 CPU 运行速度的极限,因此我们选择增加更多的 CPU。

  3. 使用多线程有两个原因。第一个是您希望任务同时运行,因为同时发生两者都是可取的——例如,您希望 GUI 在执行其他工作时继续响应单击或键盘按键(事件循环是另一种实现此目的的方法)。第二个原因是利用多个核心获得性能提升。


1

多线程对于高度可并行化的任务非常有用。CPU密集型任务非常适合。您的CPU有许多核心,许多线程可以使用许多核心。它们将使用更多的CPU时间,但最终它们将使用更少的“用户”时间。如果您的应用程序受到I/O限制,则多线程并不总是解决方案(但它可能会有所帮助)


1

0

就像所有伟大的编程工作一样,它取决于情况。总的来说,您将从一个物理存储或一个物理控制器请求文件,该控制器将以任何方式序列化请求(或更糟糕的是,在经典硬盘上导致大量的头部前后移动),并减慢已经缓慢的I/O。

另一方面,如果控制器和介质是分开的,则从它们加载数据的多个核心应该比顺序方法更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接