4

我有一个具有大量 IO 操作的应用程序,例如文件复制、压缩和在文件系统中移动文件,复制到备份服务器。

我将此程序构建为单线程。它在 2 分钟内运行。

我用 Parallel 扩展和使用 Task 构建了这个程序的另一个版本,它也几乎在 2 分钟内运行。

换句话说,由于大量的 IO,我没有看到使用 Parallels 的性能提升。

如果我将应用程序部署到刀片服务器,我会得到相同的结果吗?

刀片服务器是否比我的工作站更快/在多通道上处理 IO?

将 Parallels 与 IO 绑定应用程序一起使用没有好处吗?

4

5 回答 5

6

如果您所做的只是在系统中复制或移动文件,那么 TPL 提供的并行性对您没有多大帮助。例如,移动实际上不使用任何 CPU,它只是更改磁盘目录记录结构中的文件位置。

文件压缩是另一回事。在这里,您正在加载数据并使用 CPU 对其进行压缩,然后再将其保存到磁盘。您也许可以使用管道并行循环以更有效的方式加载/压缩/保存数据。您可以让多个线程处理不同的文件,而不是让一个线程处理每个文件。

以下代码顺序压缩大量文件,然后并行压缩。我在 i7 920 和英特尔 X25 SSD 上获得以下时间,压缩 329 张 JPG 图像,总计 800Mb 数据。

顺序:39901ms

并行:12404ms

class Program
{
    static void Main(string[] args)
    {
        string[] paths = Directory.GetFiles(@"C:\temp", "*.jpg");

        DirectoryInfo di = new DirectoryInfo(@"C:\temp");

        Stopwatch sw = new Stopwatch();
        sw.Start();
        foreach (FileInfo fi in di.GetFiles("*.jpg"))
        {
            Compress(fi);
        }
        sw.Stop();
        Console.WriteLine("Sequential: " + sw.ElapsedMilliseconds);

        Console.WriteLine("Delete the results files and then rerun...");
        Console.ReadKey();

        sw.Reset();
        sw.Start();
        Parallel.ForEach(di.GetFiles("*.jpg"), (fi) => { Compress(fi); });
        sw.Stop();

        Console.WriteLine("Parallel: " + sw.ElapsedMilliseconds);
        Console.ReadKey();
    }

    public static void Compress(FileInfo fi)
    {
        using (FileStream inFile = fi.OpenRead())
        {
            if ((File.GetAttributes(fi.FullName)
                & FileAttributes.Hidden)
                != FileAttributes.Hidden & fi.Extension != ".gz")
            {
                using (FileStream outFile =
                            File.Create(fi.FullName + ".gz"))
                {
                    using (GZipStream Compress =
                        new GZipStream(outFile,
                        CompressionMode.Compress))
                    {
                        inFile.CopyTo(Compress);
                    }
                }
            }
        }
    }
}

有关压缩代码,请参见如何:压缩文件

于 2011-03-18T04:46:26.277 回答
1

如果您在一台物理设备上移动文件,您不会看到向同一台设备发出多个并行 IO 请求带来的性能优势。该设备的运行速度已经比 CPU 慢了许多数量级,因此并行发出的多个请求仍将排队等待在设备上一一处理。您的并行代码正在被序列化,因为它们都在访问同一设备,而该设备一次不能真正处理多个请求。

如果您的磁盘控制器实现“电梯搜索”、“分散-收集”或其他无序操作,您可能会看到并行代码的性能有微小的改进,但性能差异会相对较小。

当您在许多不同的物理设备之间移动文件时,您应该发现文件 I/O 的更有价值的性能差异。您应该能够将磁盘 A 上的文件移动或复制到磁盘 A 上的某个其他位置,同时还可以将磁盘 B 上的文件复制到磁盘 C。对于许多物理设备,您不会让所有并行请求堆积起来等待满足所有请求的一台设备。

对于网络 I/O,您可能会看到类似的结果:如果一切都通过一个以太网卡/网段,您将无法实现与使用多个以太网卡和多个网段时一样多的并行性。

于 2011-03-18T05:02:03.410 回答
0

我认为并行扩展的优势可能对 CPU 操作很重要。Donnu 它应该如何影响 IO 寿。

于 2011-03-18T03:47:17.697 回答
0

我有一个在 WinForms 中实现的应用程序,它在大约 5 分钟内处理约 7,800 个 URL(下载 URL、解析内容、查找特定的数据片段,如果它找到它要查找的内容,则对该数据进行一些额外的处理。

此特定应用程序过去需要 26 到 30 分钟才能运行,但通过将代码更改为 TPL(.NET v4.0 中的任务并行库),它只需 5 分钟即可执行。该计算机是具有双四核的戴尔 T7500 工作站Xeon 处理器 (3 GHz),运行 24 GB RAM,Windows 7 Ultimate 64 位版本。

但是,它与您的情况并不完全相同,这也是 IO 密集型的。TPL 的文档表明它最初是为处理器绑定的问题集而设计的,但这并不排除在 IO 情况下使用它(正如我的应用程序向我展示的那样)。如果您至少有 4 个内核并且您的处理时间没有显着下降,那么您可能有其他实现问题阻碍了 TPL 真正高效(锁、硬盘驱动器项目等)。《使用 Microsoft .NET 进行并行编程》一书确实帮助我理解了“如何”修改您的代码才能真正利用所有这些功能。

在我看来值得一看。

于 2011-03-18T05:08:44.563 回答
0

这完全取决于您是受 CPU 限制还是 IO 限制。我建议做一些性能测试,看看你的瓶颈在哪里。

如果您发现您正在移动和压缩大量文件(到不同的磁盘,因为在同一个磁盘上的移动只是 FAT 表的更改),您可能需要考虑实现一个在移动时压缩的流文件移动器。这样可以节省移动文件后重新读取文件的额外 IO。我已经通过移动和校验和做到了这一点,就我而言,这是一个巨大的性能提升。

希望这可以帮助。

于 2011-03-18T05:01:43.853 回答