如果我需要读取大量文件,如果我将任务分成多个线程会更快吗?

Posted

技术标签:

【中文标题】如果我需要读取大量文件,如果我将任务分成多个线程会更快吗?【英文标题】:If I need to read lots of files, will it be faster if I break the task into multiple threads? 【发布时间】:2018-12-21 01:58:51 【问题描述】:

我最近接受了 NetApp 的 C++ 职位面试(他们负责大数据存储系统)。我写了一些代码来回答一个面试问题。他们的回答是“你失败了”。很难获得反馈,因为通常是在面试失败后。经过一些非常有礼貌的乞求反馈后,我得到了一些反馈。但这仍然不是很有意义。

问题来了:

给定一个目录中的一堆文件,将它们全部读取并计算单词。创建一堆线程来并行读取文件。

NetApp(对存储有很多了解的人)的共识是,它应该通过更多线程变得更快。我认为在大多数情况下,您的 I/O 限制如此之大,以至于在 1 或 2 之后它会变慢。我只是不明白如何才能变得更快,除非您在某些已知的特殊情况下(例如 SAN 或 RAID 阵列)即使在这些情况下,磁盘的顺序通道数也会饱和,并且您在几个线程之后再次受到 I/O 限制。

我认为我的代码很棒(当然)。我已经写 C++ 很多年了。我想我知道什么是好的代码。它应该只传递风格。呵呵。作为一般规则,性能优化不是你应该猜测的,它们应该被测试和测量。我只有有限的时间进行实验。但现在我很好奇。

代码在我的 GitHub 帐户中:

https://github.com/MenaceSan/CountTextWords

有人对此有意见吗?阐明他们可能一直在想什么?对代码的任何其他批评?

我的部分观点基于此:

Does multithreading make sense for IO-bound operations?

【问题讨论】:

有时候你真的比面试你的人更聪明。我同意您的评估,即这是 I/O 受限情况。几个线程可能会带来一点额外的性能,但我不会费心去超越。 它是 IO 绑定的,但是在线程读取内存中的一个块(解析文本)之后,您也会在线程中做一些实际工作。因此,您可以在那里获得一些性能提升。此外,您可以将文件缓存在内存中。在这种情况下,您将获得更好的利用率。还取决于底层的 fs 和设备。所以,在那里使用几个线程是有意义的。 是的,所以 2 个线程可能会获得一些好处。 CPU 工作可以在一个线程上完成,而另一个线程处于 i/o 等待模式。 i/o 绑定方面似乎总是比工作的 cpu 部分花费更长的时间。因此,超过 2 个线程似乎又回到了线程被浪费的同一个问题。但没有什么是100%的。在正确的硬件上,它实际上可能会从更多的线程中受益。我想他们不想让我写一个自我平衡的程序。面试?真的吗 ?呵呵。我想要干净的代码。 【参考方案1】:

答案是,正如您所推测的,这在很大程度上取决于任务的条件。而且正如你所说,在你实际测试之前你无法知道。

也就是说,这是对一家大数据存储提供商的采访。他们可能希望您假设该任务正在谈论您将为他们编写的系统(即大量非常快速的基于网络的存储),或者至少告诉他们您对任务的假设是什么。此外,他们可能希望您谈论诸如文件大小和文件数量是否重要以及它将如何影响事情之类的事情。 (以及所有其他因素 - 进行读取的计算机上的内存量、进行处理的 CPU 速度等)

你说:

NetApp(对存储有很多了解的人)的共识是,线程越多,速度越快。

他们在你的采访中告诉过你吗?如果是这样,可能是因为这就是他们在硬件和软件堆栈方面的经验。如果是 HR 的人在面试后告诉你这件事,我可能会持保留态度。工程师试图将此类信息传达给 HR,通常会以game of telephone 结束,然后再传递给您与之交谈的人,并且他们对所说内容的理解可能与您或工程师的理解不符。

如果在面试中有疑问,请解释您的假设是什么,验证面试官是否同意这些假设,如果没有,请调整它们以符合他们的要求。他们可能会做出荒谬的假设来看看你的想法,或者他们可能只是有与你不同的经历。

FWIW,听起来您对这项任务的挑战有一个合理的认识,至少对于像我这样的人每天使用的典型机器配置而言。如果您解释说这就是您的假设,我就不会为此而责备您。但并不是每个面试的人都这么想。很抱歉你没有得到这份工作,但从它的声音来看,你很快就会找到一份工作的!

【讨论】:

以上是关于如果我需要读取大量文件,如果我将任务分成多个线程会更快吗?的主要内容,如果未能解决你的问题,请参考以下文章

通过将长时间运行的任务分成单独的进程来提高程序性能

《Java并发编程实战》---- 任务执行

线程池

JS异步编程

初识进程 线程 协程:协程

java线程池