让我们假设我们有下一个任务(非常抽象):
我们有一个文件夹,要处理各种文件(文件数可能是1,2或几千)。每个文件只能按顺序处理(这意味着无法读取内存中的整个文件并在多个线程中处理它)。文件处理的结果应该是生成新文件,也是顺序写入的。如何使用所有可用的CPU内核进行操作?
我只看到两种方法:
使用由多个线程处理的任务队列。每个任务正在处理单个文件,例如从文件读取块,处理块,将块写入结果文件。
使用像Pipeline图案之类的东西。我们有一个输入线程,它以异步方式读取文件并将块发布到多个处理队列。每个线程读取自己的队列并进行块处理。然后将结果发布到输出队列。输出线程写入结果文件。所以我们有1个输入读取线程,1个输出写入线程和几个进程线程。
块处理操作不是很快,读取速度慢。
操作系统:Mac / Linux,也许是Windows。
哪种方法更好?我们还有其他解决方案吗?
答案 0 :(得分:1)
可能最简单有效的解决方案是使用单个读取器线程,低于默认优先级。如果有一个免费的CPU核心,它就会运行。这将创建一个工作线程(处理一个输入文件并将其写回)。由于这些线程以默认优先级运行,因此这将自我平衡。当所有CPU忙于处理文件时,读取器线程将不会获得太多的CPU时间,因此不会生成大量新的工作线程。
分离文件处理并将文件写回磁盘是没有意义的;这只会产生许多不成文的工作在内存中排队的可能性。
答案 1 :(得分:1)
最好的方法是编写一个简单的Task类,它可以独立完成整个操作(读取,处理,写入),因此与外部的线程不安全操作没有任何联系。然后使用任务队列,其中固定数量的线程可以获取这些任务并处理它们。大量线程通常是核心* 2.
可以在数学上证明,选项2总是等于或慢于基于任务的解决方案,并且在所有情况下它都会更复杂。选项2更可行的唯一情况是线程切换成为实际的瓶颈。 I.E.如果你的服务器有1000个并发但有状态的连接而只有一个网卡,那么有1个网络线程可以为1000个处理线程提供服务,而不是在通过线路发送的每个字节上唤醒1000个线程。 / p>
基于任务的解决方案还可以更轻松地衡量吞吐量并比较其他线程对其的影响,因为您可以简单地在任务/秒内进行测量。
答案 2 :(得分:0)
这两种方法都有一些优点和缺点。
单读者
处理线程中的读取:
您也可以使用在一个队列中写入的并行读取器,而不是从该队列处理的内容(更复杂的编程:-)但在某些情况下有效。
好吧,并行作家也可以工作。
此外,您可以在不同的本地磁盘(不是目录,而是物理磁盘)之间分发文件。如果并行完成,这肯定会提高您的读/写性能。