如何为多个文件处理选择最佳的I/O策略



假设我们有一个下一个任务(非常抽象(:

我们有一个文件夹,其中包含各种文件以进行处理(文件计数可能1、2或几千(。每个文件只能顺序处理(这意味着不可能在内存中读取整个文件并在多个线程中处理它(。文件处理的结果应生成新文件,也应依次编写。如何使用所有可用的CPU内核?

我只看到两种方法:

  1. 使用由多个线程处理的任务队列。每个任务正在处理单个文件,例如从文件中读取块,处理块,将块写入结果文件。

  2. 使用管道模式之类的东西。我们有一个输入线程,该线程以异步方式读取文件,并将块发布到几个处理队列。每个线程读取自己的队列并进行块处理。然后发布结果以输出队列。输出线程写入结果文件。因此,我们有1个输入读数线程,1个输出编写线程和几个进程线程。

块处理不是很快操作,然后阅读较慢。

OS:Mac/linux,也许是Windows。

哪种方法更好?我们还有其他解决方案吗?

最好的方法是编写一个简单的任务类,该类别可以完成整个操作(读取,process,process,write( - 单位,因此与外部,线程安全操作无关。然后,使用固定数量的线程可以获取这些任务并处理它们的任务队列。很多线程通常是内核 *2。

可以在数学上证明选项2总是比基于任务的解决方案相等或慢,并且在所有情况下都会更加复杂。选项2更可行的唯一情况是螺纹切换成为实际的瓶颈。IE。如果您的服务器具有1000个并发但状态连接的服务器,但只有一张网卡,那么有1个网络线程为1000个处理线程提供了一个更有效的效率,而不是在线上发送的每个字节上唤醒1000个线程。<<<<<<<<<<<<<<<<<<<<<<<<<<<</p>

基于任务的解决方案还使测量吞吐量并比较其他线程如何影响它变得更加容易,因为您可以简单地在任务/秒中测量。

最简单的有效解决方案可能是具有单个读取器线程,低于默认优先级。如果有一个免费的CPU核心,则可以运行。这将创建一个单个工作线程(处理一个输入文件并将其写回(。当这些线程以默认优先级运行时,这将自我平衡。当所有CPU都忙于处理文件时,读取器线程将无法获得太多的CPU时间,因此不会生成很多新的工作线程。

将文件的处理并将其写回磁盘没有真正的意义。这只是产生了许多不成文作品在内存中排队的可能性。

两种方法中都有某些优点和缺点。

单读者

  1. pro:从处理中提供良好的学术抽象层,并可能以更好的编程模型最终出现。
  2. pro:另外,只要您可以为所有其他线程提供工作(如果游行的速度比您的读取操作速度要慢得多(并且文件系统不会分散,那么您可以更好地利用系统。
  3. con:#2很难实现,因此很可能不会存在这个优势。
  4. con:编程更难,您需要在顶部进行FIFO或其他队列和同步。

处理线程中的读取:

  1. pro:易于实现,不需要队列或同步
  2. pro:在零散的文件系统中更好地工作:可以通过OS或硬件来优化多个IO请求,以减少延迟。另外,延迟较低的请求将更快地开始处理,无论在单一读者中,无论如何都必须等待。
  3. pro:读取操作本身具有一个非系统部分,该部分也可以在线程中运行并成为并行处理的一部分。
  4. con:在非碎片系统中可能会松动,因为它会增加一些类似碎片的行为。

顺便说一句,还有更多可能的处理方案。您忘了提到的一个是拥有一个单个作者线程,您的处理转储在队列中会导致后台进程编写它。这可能会给您带来更多的提升。每个线程都不需要等待写字。

您也可以使用以一个队列写入的并行读取器,而不是从该队列中获取的处理(甚至更复杂的编程:-)但是在某些情况下可以使用。

好吧,平行作家也可以工作。

您也可以在不同的 local 磁盘(不是目录,而是物理磁盘(之间分配文件的问题。如果并行完成,这肯定会增加您的读/写作性能。

最新更新