多线程对 IO 密集型任务没有帮助?
Posted
技术标签:
【中文标题】多线程对 IO 密集型任务没有帮助?【英文标题】:Mulithreading does not help for IO intensive task? 【发布时间】:2020-04-09 18:10:55 【问题描述】:我需要复制一组文件,每个文件的大小从 1MB 到 700MB 不等。复制每个文件后,我需要根据 md5sum.txt 中的条目验证每个文件的校验和。
我想优化这个任务,因此通过在多个线程之间分配负载来评估性能。结果并不如预期。我原以为复制和验证所花费的时间会随着线程数的增加而减少,但实际花费的时间却增加了。
我修改了这个链接https://***.com/a/22285532/1568395分享的ThreadPool源码,实现了线程池。
应用程序的源代码可以在这里找到 https://github.com/saai63/ThreadPool
不同线程数的结果如下图,
根据我的阅读,可能的原因可能是所有任务现在都是 IO 绑定任务,因此所有线程都将在 IO 操作上被阻塞,因此无法并行运行,因为这里的共享资源是 HDD。我也了解硬盘控制器试图通过减少寻道时间来优化磁盘访问。磁盘喜欢顺序访问模式,任何并发访问都会破坏这种模式,从而导致大文件的延迟。
这是延迟的唯一原因还是还有其他一些因素?为什么时间会随着线程数的增加而增加?
【问题讨论】:
线程池不是数据并行技术。它们是数据并行化代码使用的低级功能,但本身不提供任何东西。您可以创建 5 个“工作人员”,每个工作人员处理 1/5 的文件。这些工作人员可以从该池中获取他们的线程,但最终,数据分区和工作人员将加快速度。但是,您不会获得 5 倍的性能提升 @PanagiotisKanavos :我没想到时间会减少“n”倍,但至少比通过单线程实现的要好。看到的结果是反直觉的,因此是查询。 【参考方案1】:IO 总是比 CPU 慢得多。当多个线程尝试从一个 IO 设备读取时,它们通常实现的是对设备的“牛市冲”,并增加了 IO 操作的“随机性”,从而使其速度变慢。更少的线程有更大的机会进行顺序操作,众所周知,顺序操作速度更快。
【讨论】:
好的。也可以将其外推到流程吗?如果有 2 个进程试图同时将一些数据复制到同一个分区,那么这两个进程都会变慢吗?这种行为是随机的还是总是如此? 是的。从 OS 调度程序获取时间的是线程,而不是进程。【参考方案2】:在多线程的情况下,您在线程之间共享 CPU。每当运行线程进入某种等待状态时,CPU 就会在线程之间切换。
这里你有 IO 绑定任务,没有必要让你的程序多线程,因为它们都将依赖于单个 IO 设备。
即使你实现了多进程解决方案(同一个节点上的多个进程),所有进程都将等待同一个 IO 设备,不会进行任何性能优化。
一种解决方案是构建某种具有共享磁盘的多节点解决方案,同时支持多客户端访问。
使用这种方法,您可以在多个节点之间划分任务,访问同一个磁盘并执行操作。
编辑:
我认为时间的增加是因为操作系统为多个线程提供服务所花费的时间。
在线程之间切换 CPU 和 IO 设备会随着线程数量的增加而消耗,上下文切换是计算密集型任务,并且在线程之间切换时会失去 IO/CPU 缓存性能。
【讨论】:
但这仍然不能解释当我使用多个线程来完成这项工作时,10 倍的巨大增长 @saai63 我已经编辑了我的答案,我希望它能解释。以上是关于多线程对 IO 密集型任务没有帮助?的主要内容,如果未能解决你的问题,请参考以下文章