在C#中,我想使用TPL的Parallel.ForEach来利用现代多核CPU,但我的问题更多是假设性的;
实际上使用多线程是否意味着并行加载文件需要更长的时间(尽管可以使用尽可能多的CPU核心),而顺序加载每个文件则需要较少的CPU利用率?
换句话说:
多线程的重点是什么?并行执行更多任务,但速度更慢,还是专注于一项任务上使用所有计算资源?
对于从磁盘加载文件,这可能会使事情变得更慢。操作系统试图将文件在磁盘上排列,以便每个文件只需要进行一次昂贵的磁盘查找。如果有很多线程读取很多文件,则线程之间会争用访问磁盘的权限,并且每次下一个线程获取轮换时,您将不得不重新定位到文件中的正确位置。
您可以使用正好两个线程。设置一个后台线程来加载所有文件,让另一个线程保持可用状态以执行其他任务,例如处理用户输入。 在C# winforms中,您可以使用BackgroundWorker控件轻松实现此操作。
您提出了多个问题,所以我将我的回答分成了多个部分:
多线程可能对加载速度没有影响,这取决于加载过程中的瓶颈是什么。如果您正在从磁盘或数据库中加载大量数据,则 I/O 可能是限制因素。另一方面,如果“加载”涉及使用某些数据进行大量 CPU 工作,则使用多线程可能会加快速度。
一般来说,您无法将“所有计算资源集中在一个任务上”。一些多核处理器具有超频单个核心的能力,但这种速度提升不等于通过使用多线程/多进程充分利用所有核心所能获得的潜在性能优势。换句话说,它是不对称的——如果您拥有一个 4 核心 1Ghz 的 CPU,它不会能够通过禁用其他核心来将单个核心超频到 4ghz。事实上,这就是行业首先采用多核心的原因——至少目前我们已经达到了单个 CPU 运行速度的极限,因此我们选择增加更多的 CPU。
使用多线程有两个原因。第一个是您希望任务同时运行,因为同时发生两者都是可取的——例如,您希望 GUI 在执行其他工作时继续响应单击或键盘按键(事件循环是另一种实现此目的的方法)。第二个原因是利用多个核心获得性能提升。
多线程对于高度可并行化的任务非常有用。CPU密集型任务非常适合。您的CPU有许多核心,许多线程可以使用许多核心。它们将使用更多的CPU时间,但最终它们将使用更少的“用户”时间。如果您的应用程序受到I/O限制,则多线程并不总是解决方案(但它可能会有所帮助)
首先了解多线程和并行处理之间的区别可能会有所帮助,因为我经常看到它们被交替使用。Joseph Albahari撰写了一份非常有趣的指南,介绍了这个主题:C#中的线程-第5部分-并行处理
就像所有伟大的编程工作一样,它取决于情况。总的来说,您将从一个物理存储或一个物理控制器请求文件,该控制器将以任何方式序列化请求(或更糟糕的是,在经典硬盘上导致大量的头部前后移动),并减慢已经缓慢的I/O。
另一方面,如果控制器和介质是分开的,则从它们加载数据的多个核心应该比顺序方法更好。