C# 并行扩展
我有一个具有大量IO操作的应用程序,例如文件复制、压缩和在文件系统中移动文件、复制到备份服务器 我将这个程序构建为单线程。它在2分钟内运行 我用并行扩展和Task构建了这个程序的另一个版本,它也几乎在2分钟内运行 换句话说,由于IO太重,我没有看到通过使用并行来提高性能 如果将应用程序部署到刀片服务器,会得到同样的结果吗 刀片服务器在多通道上处理IO是否比我的工作站更快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绑定的应用程序中使用并行程序没有任何好处?我认为并行扩展在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建议允许每个线程从头到尾获取一个文件……这也是我首先要尝试的,以查看性能如何变化。