在Goetz的“实践中的Java并发”中,在第101页的脚注中,他写道:“对于这样的计算问题,不进行I / O并且不访问共享数据,Ncpu或Ncpu + 1线程可以产生最佳吞吐量;更多线程没有帮助,实际上可能会降低性能......“
我的问题是,在执行文件写入,文件读取,文件删除等I / O操作时,是否有用于实现最高性能的线程数的指导原则?我知道这只是一个指导编号,因为磁盘速度和许多其他因素都会影响到这一点。
不过,我想知道:在4-cpu机器上,20个线程可以将1000个单独的文件写入磁盘,而不是4个线程吗?
答案 0 :(得分:11)
实际上,I / O绑定的应用程序仍然可以从多线程中获益,因为并行读取或写入一些文件要快得多。特别是在整体吞吐量受网络延迟影响的情况下。但同样的情况是,一个线程可以处理它读取的最后一个东西,而另一个线程正在忙于读取,从而允许更高的CPU利用率。
我们可以整天谈论理论,但正确的答案是使线程数可配置。我想你会发现,将它增加到1可以提高你的速度,但也会有一个收益递减的点。
答案 1 :(得分:4)
是的,在4 CPU机器上,20个线程绝对能够比4个线程更快地写入磁盘。许多实际程序的I / O限制超过CPU限制。但是,它非常依赖于您的磁盘以及其他线程正在执行的CPU工作量,然后它们最终会等待这些磁盘。
如果你的所有线程都只是写入磁盘并且什么都不做,那么4 CPU机器上的1个线程实际上可能是写入磁盘的最快方式。它完全取决于您拥有的磁盘数量,您正在编写的数据量以及您的操作系统在I / O调度方面的优势。您的具体问题表明您希望4个线程都写入同一个文件。这没有多大意义,在任何实际情况下,我都无法想象如何更快。 (你必须提前分配文件,然后每个线程将寻找()到不同的位置,并且当每个线程试图写一些块时,你最终只是颠倒了写头。)
当您受网络限制时,多线程的优势会更加简单。即:在数据库服务器或Web浏览器等上等待。在那里,你在等待多个外部资源。
答案 2 :(得分:3)
与所有与绩效相关的事情一样。
如果您受I / O限制,那么添加线程根本无法帮助您。 (好吧,正如Steven Sudit指出的那样,你可能会提高性能,但它会很小) 如果您不是I / O绑定,那么添加线程可能会有所帮助
不要试图变得聪明,但最好的方法是找出它并查看适合您特定情况的内容。
编辑:根据评论更新
答案 3 :(得分:3)
另见Will using multiple threads with a RandomAccessFile help performance?
<强>更新强> 我在那里添加了一个基准。
答案 4 :(得分:2)
如果您使用的是同步I / O,那么您的机器可以处理的每个同时I / O请求都应该有一个线程。在单主轴单硬盘的情况下,即1(您可以读取或写入,但不能同时读取或写入)。对于可以同时处理许多I / O请求的磁盘,可能会同时处理多个请求。
换句话说,这不受CPU数量的限制,因为I / O除了提交请求和等待之外并没有真正击中CPU。 See here for a better explanation.
还有其他一堆蠕虫可以在任何给定时间内处理飞行中有多少I / O请求。
答案 5 :(得分:1)
Ncpu +期望的并发IO活动数是我通常的数字。
关键不在于20个线程可以比4个线程更快地将单个文件写入磁盘。如果每个cpu只有1个线程,那么在写入磁盘时,您的进程将无法使用托管正在执行文件IO的线程的cpu。该CPU实际上正在等待写入文件,而如果你还有一个线程,它可以使用CPU在过渡期间进行实际处理。
答案 6 :(得分:0)
如果您对该线程执行的唯一操作是写入磁盘,那么您的性能提升可以忽略不计甚至有害,因为通常的驱动程序针对硬盘驱动器的顺序读取进行了优化,因此您可以在文件中转换顺序写入几次“随机”写作。
如果在性能方面中针对不同磁盘,不同网卡或不同数据库服务器执行I / O,多线程只能帮助您解决I / O限制问题。尽管如此,就观察到的性能而言,差异可能更大。
例如,假设您通过网络向多个不同的接收器发送了多个文件。您仍然是网络绑定的,因此您的最高速度不会高于100Mb / S,但是,如果您使用20个线程,那么该过程将更加公平。