【问题标题】:Use multithreading for multiple file copies对多个文件副本使用多线程
【发布时间】:2014-12-23 12:22:11
【问题描述】:

我必须复制大量文件(10000 个文件)

因为复制需要很长时间。 我尝试使用两个线程而不是单线程,一个用于复制列表中的奇数文件,另一个用于复制列表中的偶数

我用过这段代码:

ThreadPool.QueueUserWorkItem(new WaitCallback(this.RunFileCopy),object)

但是使用单线程和使用双线程的时间没有显着差异。

这可能是什么原因?

【问题讨论】:

  • 原因是因为复制文件主要是I/O操作,而不是CPU。您可以做的一件事是使用 SSD(它更适合并行读/写)。除此之外,你被搞砸了。顺便说一句:如果您使用任何编程语言,请适当地标记您的问题。
  • 非常感谢。但我无权更改用户硬盘

标签: c# multithreading io parallel-processing file-copying


【解决方案1】:

文件复制不是 CPU 进程,它是 IO 进程,因此多线程或并行对您没有帮助。

几乎在所有情况下,多线程都会减慢您的速度。如果磁盘也是 SSD,它的 r/w 速度有限,并且它也会通过单线程有效地使用它。如果您使用并行性,您只会将您的速度分成几部分,这将为 HDD 带来巨大的开销

当您从不同的光盘读取并写入不同的光盘时,多线程仅在多个光盘情况下为您提供帮助。

如果文件太小。在大多数情况下,压缩和解压缩目标驱动器上的文件会更快,如果您使用低压缩率压缩文件会更快

using System.IO;
using System.IO.Compression;

.....

string startPath = @"c:\example\start";
string zipPath = @"c:\example\result.zip";
string extractPath = @"c:\example\extract";

ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, true);

ZipFile.ExtractToDirectory(zipPath, extractPath);

更多实现细节在这里

How to: Compress and Extract Files

【讨论】:

    【解决方案2】:

    我将在这里提供少数意见。每个人都告诉你磁盘 I/O 会阻止你从多个线程中获得任何加速。那是……有点……没错,但是……

    给定一个磁盘请求,操作系统只能选择将磁头移动到磁盘上通过文件访问隐含选择的点,通常会产生平均一半的全行程寻道时间(几十毫秒)和旋转访问数据的延迟(另外 10 毫秒)。并且坚持单个磁盘请求,这是一个非常可怕(且不可避免)的成本。

    因为磁盘访问需要很长时间,操作系统有足够的 CPU 来考虑当有多个请求时访问磁盘的最佳顺序,如果它们发生在它已经在等待磁盘做某事的时候。操作系统通常使用elevator algorithm 执行此操作,从而导致磁头一次通过一个方向有效地扫描磁盘,并在达到“最远”访问时有效地在另一个方向扫描.

    这个想法很简单:如果您完全按照它们发生的时间顺序处理多个磁盘请求,磁盘磁头可能会在磁盘周围随机跳跃(假设文件是​​随机放置的),从而导致每个访问时的完全搜索 + 旋转延迟。按顺序处理 1000 次实时访问后,将发生 1000 次平均半满搜索。艾克。

    相反,如果给定 N 个近乎同时的访问,操作系统可以按这些访问将接触的物理柱面排序这些访问,然后按柱面顺序处理它们。 1000 次实时访问,按柱面顺序处理(即使是随机文件分布),每个柱面可能有一个请求。现在磁头只需从一个柱面移动到下一个柱面,这比平均寻道要少得多。

    因此,拥有大量请求应该有助于操作系统做出更好的访问顺序决策。

    由于 OP 有很多文件,他没有理由不能运行 很多 个线程,每个线程都复制自己的文件并产生对磁盘位置的需求。他希望每个线程发出一个完整磁道之类的读写操作,以便当磁头到达柱面时,读取或写入一个完整磁道(假设操作系统将文件连续放置在一个磁道上它可以)。

    OP 希望确保他的机器有足够的 RAM 来缓冲他的线程数乘以轨道大小。复制期间 4 Gb 空闲的 8 Gb 机器本质上具有 4 Gb 磁盘缓存。每首曲目 100Kb(我看了很久)暗示 10,000 个线程的“空间”。我严重怀疑他需要那么多;大多数情况下,他需要足够的线程来压倒磁盘上的柱面数量。我肯定会考虑几百个线程。

    两个线程肯定是不够的。 (当你要求它复制一堆文件时,Windows 似乎使用一个线程。这对我来说总是很愚蠢)。

    另一位发帖人建议压缩文件。有很多线程,并且所有东西都在磁盘上等待(电梯算法不会改变这一点,只是平均等待时间),许多线程可以承受在压缩时抛出计算周期。这对阅读没有帮助;文件是读取时的样子。但它可能会缩短要写入的数据量,并有效地在内存中提供更大的缓冲区,从而提供一些额外的加速。

    注意:如果有 SSD,则没有物理柱面,因此没有寻道时间,电梯算法也没有什么可优化的。在这里,很多线程不会购买任何气缸订购时间。他们也不应该受到伤害。

    【讨论】:

      猜你喜欢
      • 2012-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 2015-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多