我需要复制一组文件,每个文件的大小在1MB到700MB之间。复制每个文件后,需要根据md5sum.txt中的条目验证每个文件的校验和。我想优化此任务,因此通过在多个线程之间分配负载来评估性能。结果与预期不符。我原本希望复制和验证所花费的时间会随着线程数量的增加而减少,但是实际上所花费的时间却增加了。
我已经修改了在此链接https://stackoverflow.com/a/22285532/1568395中共享的ThreadPool源代码以实现线程池。
该应用程序的源代码可以在这里找到https://github.com/saai63/ThreadPool
各种线程数的结果如下所示,
根据我的阅读,可能的原因可能是所有任务现在都是与IO绑定的任务,因此所有线程都将在IO操作中被阻塞,因此不能并行运行,因为共享资源是HDD。我也了解HDD控制器会尝试通过减少查找时间来优化磁盘访问。磁盘喜欢顺序访问模式,任何并发访问都会破坏这种模式,从而延迟大文件。
这是造成延迟的唯一原因,还是有其他一些因素?请问有人可以帮助您理解为什么时间随着线程数的增加而增加吗?
IO总是比CPU慢得多。当多个线程尝试从IO设备读取时,它们通常会达到对设备的“狂奔”,并增加IO操作的“随机性”,从而使其运行速度变慢。更少的线程有更大的顺序操作机会,这是众所周知的更快。
如果是多线程,则在线程之间共享CPU。每当运行线程进入某种等待状态时,CPU就会在线程之间切换。
这里您有与IO绑定的任务,没有必要使您的程序成为多线程,因为它们都将依赖单个IO设备。
即使实现多进程解决方案(同一节点上有多个进程),所有进程也将等待同一IO设备,并且不会进行任何性能优化。
一种解决方案是使用共享磁盘同时支持多客户端访问来构建某种多节点解决方案。
使用这种方法,您可以在多个节点之间划分任务,访问同一磁盘并执行操作。