C# 并行扩展

C# 并行扩展,c#,.net,io,parallel-processing,parallel-extensions,C#,.net,Io,Parallel Processing,Parallel Extensions,我有一个具有大量IO操作的应用程序,例如文件复制、压缩和在文件系统中移动文件、复制到备份服务器 我将这个程序构建为单线程。它在2分钟内运行 我用并行扩展和Task构建了这个程序的另一个版本,它也几乎在2分钟内运行 换句话说,由于IO太重,我没有看到通过使用并行来提高性能 如果将应用程序部署到刀片服务器,会得到同样的结果吗 刀片服务器在多通道上处理IO是否比我的工作站更快 在IO绑定的应用程序中使用并行程序没有任何好处?我认为并行扩展在CPU操作方面的优势可能非常显著。Donnu它应该如何影响IO

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

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

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

换句话说,由于IO太重,我没有看到通过使用并行来提高性能

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

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


在IO绑定的应用程序中使用并行程序没有任何好处?

我认为并行扩展在CPU操作方面的优势可能非常显著。Donnu它应该如何影响IO tho。

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

文件压缩是另一回事。在这里,您正在加载数据,并在将其保存到磁盘之前使用CPU对其进行压缩。您可以使用或以更有效的方式加载/压缩/保存数据。与其让一个线程压缩每个文件,还可以让多个线程处理不同的文件

下面的代码先按顺序压缩文件,然后并行压缩。在i7 920和intel 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);
                    }
                }
            }
        }
    }
}

有关压缩代码,请参见

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

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


希望这能有所帮助。

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

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

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


您可能会在网络I/O中看到类似的结果:如果所有内容都通过一个以太网卡/网段,那么您将无法实现与使用多个以太网卡和多个网段时相同的并行性。

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

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

不过,这与您的情况并不完全相同,这也是非常IO密集型的。关于TPL的文档说明,它最初是为处理器限制的问题集设计的,但这并不排除在IO情况下使用它(正如我的应用程序向我演示的那样)。如果您至少有4个内核,并且您的处理时间没有显著减少,那么您可能存在其他实施问题,这些问题阻碍了TPL的真正有效性(锁、硬盘项目等)。这本书《使用Microsoft.NET并行编程》确实帮助我理解了“如何”您的代码需要修改以真正利用所有这些功能


在我看来,值得一看。

您正在进行大量的I/O操作,因此这似乎是一个瓶颈。如果它是计算密集型的,您很可能会看到差异,因为它实际上是在使用CPU。在刀片服务器上如何?这会有区别吗?刀片服务器的区别在于它可能具有不同的IO禁令相对于CPU处理能力的dwidth。+1建议允许每个线程从头到尾获取一个文件……这也是我首先要尝试的,以查看性能如何变化。