`
yesjavame
  • 浏览: 678832 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

.NET并行库测试实例

阅读更多

.NET并行库测试实例

并行库存应用场景:
并行计算首要目的是提高CPU的计算能力,简单说程序应该是以CPU密集型运算为主的,如果你的程序
是IO(磁盘和网络)密集型运算,并行计算并不能对你的程序有多大的提高。有时反而会有影响。我们
还是以事实来说话:


namespace ParallelTest
{
static class Program
{
static void Compute(int i)
{
Thread.Sleep(20);
}
[STAThread]
static void Main()
{
DateTime start = DateTime.Now;


for(int i=0;i<100;i++){
Compute(i);
}

TimeSpan ts = DateTime.Now - start;
System.Console.WriteLine("TotalMilliseconds is : {0}",ts.TotalMilliseconds);
}
}
}

我们用Thread.Sleep(20);来模拟一个CPU密集型运算,它只和CPU调度有关,不存在IO运算。这个传统的程序
在我的Pentium D 300的机器上跑的时间是3125ms,理论上它应该是2000,但那上方法内运行的代码所占用的时间,
方法帧的生成,CPU的调度都是额外的时间开销,所以这个程序跑了3125ms.这是我运行20次得到的相同的时间
(当然也就是平均时间了)。

现在我们用并行代码来运行这个程序:

namespace ParallelTest
{
static class Program
{
static void Compute(int i)
{
Thread.Sleep(20);
}
[STAThread]
static void Main()
{
DateTime start = DateTime.Now;


Parallel.For(0, 100, delegate(int i) { Compute(i); });


TimeSpan ts = DateTime.Now - start;
System.Console.WriteLine("TotalMilliseconds is : {0}",ts.TotalMilliseconds);
}
}
}

这些我运行20次,它们的时间大多数时候是相同的,有十多次是1093.75,同时还有1109.375,1140.625,
1081.175之类的时间,总之它们的平均时间比3125少了几乎是两倍,也就是两个CPU运行方法中代码的时间应该
为1000ms,而方法帧生成,CPU调度只占用实际代执行的1/10左右。

更强的是当我把Sleep(20)改成Sleep(50)时,我们知道两个CPU执行100次应该至少2500ms,但实际上这个平均值是
2063.75ms,说明并代码并不只是两个CPU的两个线程在运行,一定还利用超线程/纤程等技术。而非并行代码运行
的时间是6250ms,没有任何让人惊喜的地方。


下面我们再来来看一下本地IO的例子。

我把我的一个目录从E分区复制到D分区,目录是一个图片库存,两级子目录,其中都是平时用到的图片和一些不可
告人(别揭发我啊)的图片按类型分类的。

我们先用传统的编程方式来实现:

namespace ParallelTest
{

static class Program
{

static void CopyDir(DirectoryInfo s, DirectoryInfo d)
{
if (!d.Exists)
d.Create();
foreach (DirectoryInfo sd in s.GetDirectories()) {
CopyDir(sd, new DirectoryInfo(Path.Combine(d.FullName,sd.Name)));
}
foreach (FileInfo f in s.GetFiles()) {
f.CopyTo(new FileInfo(Path.Combine(d.FullName,f.Name)).FullName);
}

}

[STAThread]
static void Main()
{
DateTime start = DateTime.Now;

CopyDir(new DirectoryInfo("E:\\BigTools\\lspic"),new DirectoryInfo("d:\\"));

TimeSpan ts = DateTime.Now - start;
System.Console.WriteLine("times is : {0}",ts.TotalMilliseconds);

}
}
}
这段代码打印的时间是 75187.5ms.
改用并行代码:

namespace ParallelTest
{

static class Program
{

private static void CopyDir(DirectoryInfo s, DirectoryInfo d)
{
if (!d.Exists)
d.Create();
Parallel.Invoke(
() =>
{
Parallel.ForEach(s.GetFiles(), f =>
{
var t = new FileInfo(Path.Combine(d.FullName, f.Name));
f.CopyTo(t.FullName);

});
},
() =>
{
Parallel.ForEach(s.GetDirectories(), subs =>
{
var subd = new DirectoryInfo(Path.Combine(d.FullName, subs.Name));
CopyDir(subs, subd);
});
});
}

[STAThread]
static void Main()
{
DateTime start = DateTime.Now;

CopyDir(new DirectoryInfo("E:\\BigTools\\lspic"),new DirectoryInfo("d:\\"));

TimeSpan ts = DateTime.Now - start;
System.Console.WriteLine("times is : {0}",ts.TotalMilliseconds);

}
}
}


结果时间只用了33187.5ms,我们看这段程序的两个分支都在并行执行,首先把当前目录中文件和子目录的处理
作为两个匿名方法分配给Parallel.Invoke()方法来并行处理,然后在其中的循环又分别使用并行代码来执行。
时间节省了一倍多。


但是,这并不是真正的IO密集型运算。因为图片文件都在几十k左右,生成C#的目录对象和文件对象本身花的时间
和真正的IO读写的时间比例没有拉开。也就是IO操作还没到饱和。所以并行代码不仅充分利用了CPU,也大大利用
了IO性能。

但当我在另一个目录中放入6个600M左右(Myeclipse7.2的安装文件改名后复制)的文件时,结果就明显了:
非并行代码:231453.125ms,并行代码:573453.125ms.
令人吃惊的是并行代码不但不能提高程序的性能,反而极大地影响性能。无论人多少CPU在工作,磁盘IO的吞吐量是
有限的。而过多的并行操作反而增加了切换的频度,使IO操作本身增加了大量的OverHead.

当并行代码的程序正在运行的时候,我看了一下目标盘同时生成了四个文件,证明了我上面使用超线程或纤程的
猜想,但我的CPU在系统属性中无法看出支持超线程。

如果你亲手试一下这个例子,6个文件正好说明问题。当运行并行代码时,同时有四个线程(或纤程)在运行,因为
刚开运行时目录盘下立即产生四个文件,然后磁盘不停地嘎嘎嘎嘎响,但时间比四个文件单线程执行要多好久。大约在
450000ms才执行完成,然后余下的两个文件同样在并行代码下COPY,时间不很短。说明并行代码在多并发情况下,对密
集型IO操作不但不能提高性能,还大量浪费环境切换的开销。而实际有多少个并发,目前的并行库还不能控制。
即使只有两个文件,非并行代码和并行代码执行的时间分别为73890.625ms,168343.75ms。并行代码多花了一倍多的时间。


真正的本地IO操作C#代码下运行不可能很快,因为它没有DMA通道的支持,从托管代码到系统调用,每一次COPY一定数量的
字节都必须经过5次内核模式/用户模式的上下文切换和3次读缓冲/应用程序内存/写缓冲的复制。解决密集型IO的方案应该
是IO的并行吞吐能力和ZeorCopy之类的DMA通道才是首选,如java的FileChannel可以直接transferTo到一个输出流,比如
网络IO这样在文件和网络IO之间直接建立DMA通道而不需要反复切换和COPY。

所以,任何技术都有它的合适应用场景,比如在一个CPU的机器上单线程无IO操作运算肯定要比多线程还要快,因为无论如何
同时只有一个线程运行,如果没有IO阻塞,多线程反而增加线程调度的开销。并行编程也同样,主要看我们具体的执行逻辑,
根据具体的情况选择适当的技术。

分享到:
评论

相关推荐

    .net 压力测试代码实例

    本文将深入探讨.NET压力测试的概念,并通过一个具体的代码实例来讲解如何进行压力测试。 首先,理解压力测试的基本概念:压力测试是通过模拟超出正常工作负荷的情况来检查系统性能、稳定性和资源管理能力的一种测试...

    精通C#3.0与.net3.5高级编程 实例下载

    5. 并发和多线程:C# 3.0引入了Task Parallel Library(TPL),用于更高效地管理并发和并行计算,实例将演示如何利用TPL来提高程序性能。 6. 自动化测试:可能包含使用NUnit或MSTest等单元测试框架编写测试用例的...

    多线程-VB.net开发实例_vb.net多线程_

    7. **调试与测试**:在VB.NET中,可以使用Visual Studio的调试工具来跟踪和分析多线程程序的行为。通过设置断点,观察线程状态,检查共享变量,可以更好地理解线程如何工作和交互。 通过理解和应用这些知识点,...

    Visual C++ .NET编程实例pdf

    6. **多线程编程**: .NET框架和C++都支持多线程编程,这对于创建并发和并行应用程序至关重要。在Visual C++ .NET中,开发者可以使用System.Threading命名空间和C++的线程类来管理线程。 7. **组件重用与Assemblies*...

    .NET的WF测试示例

    在".NET的WF测试示例"中,我们可以假设这个项目是为了展示如何在实际应用中使用WF来构建和测试业务流程。这个示例可能包括创建工作流、实例化工作流、执行工作流以及对工作流进行调试等步骤。其中,数据库连接和绑定...

    VB.NET学习教程(PDF)

    9. **并行编程与多线程**:VB.NET提供了对多核处理器和并发编程的良好支持,如Task Parallel Library (TPL) 和 Concurrent Collections,帮助你编写高性能的应用。 10. **调试与单元测试**:学习使用Visual Studio...

    .NET-4.0中的并行开发.docx

    另一个重要的概念是任务并行库(TPL,Task Parallel Library),它包含在.NET Framework 4.0中。TPL提供了一个任务导向的编程模型,允许开发者将任务作为独立的工作单元进行处理。任务可以异步执行,相互等待,或者...

    VS.net九大案例代码

    案例可能包括如何创建并管理线程,使用任务并行库(TPL)进行并发编程,以及处理锁和同步问题。 8. **Azure云服务**:VS.NET可以用于开发Azure应用程序,案例可能涉及如何部署Web应用到Azure App Service,存储数据到...

    《Visual Basic .NET专业项目实例开发》源代码

    6. **多线程**:掌握如何在VB.NET中创建和管理线程,以实现并行处理和优化性能。 7. **网络编程**:了解如何使用VB.NET实现客户端和服务器之间的通信,例如HTTP请求、TCP/IP套接字编程等。 8. **XML和Web服务**:...

    C#.NET多线程实例6个(包括多线程基本使用,多线程互斥等全部多线程使用实例)完整源码

    6. **异步编程模型**:C#.NET提供了基于事件的异步模式(EAP)和任务并行库(TPL)。实例可能包括了`async/await`关键字的使用,它们简化了异步操作的编写,使代码更易读和维护。 每个实例都应包括详细的注释和步骤...

    .NET 4.0 技术亮点剖析

    因此,设计高效的并行算法和进行细致的测试是必不可少的步骤。 - **TPL 应用实例**:通过一个简单的示例来展示如何使用 TPL 进行并行计算。例如,检查一台计算机是否连接到互联网时,可以通过并行执行对各个网卡的 ...

    C#并行实例

    通常,我们会设计一个基准测试,分别以顺序和并行方式执行相同任务,然后比较执行时间,以此评估并行化的性能提升。 总结,C#的并行实例展示了如何利用现代硬件的优势提高程序性能。通过理解和应用TPL和PLINQ,...

    高清彩版 Pro .NET 4 Parallel Programming in C#

    1. 使用.NET 4任务并行库(Task Parallel Library,简称TPL)来简化并行编程任务的创建和管理。 2. 介绍如何在多任务间同步共享数据,以保证数据的一致性和线程安全。 3. 讨论并行执行的协调机制,包括任务调度和...

    .NET_Test_Automation_Recipes

    这些源代码是作者为了详细阐述各种自动化测试策略和技术而编写的实例,覆盖了测试的不同阶段和方面。下面将详细探讨每个章节涉及的知识点。 1. **Ch01Code.txt** - 这个章节通常会介绍自动化测试的基础,包括测试的...

    .NET微服务框架antservicestack

    使用antservicestack可以快速构建分布式系统,每个服务都可以独立开发、测试、部署,使得团队可以并行开发,提高效率。此外,由于antservicestack的微服务特性,它适用于需要高可用性和可扩展性的大型项目,例如...

    毕业设计:基于ASP.NET MVC实现的后台管理系统.zip

    它与ASP.NET Web Forms并行存在,但更侧重于分离关注点和测试驱动开发。 2. **模型-视图-控制器(MVC)模式**:MVC模式是一种软件设计模式,用于将业务逻辑、用户界面和数据访问分离开来。模型负责处理数据和业务...

    VB.NET调试技术手册

    《VB.NET调试技术手册》是一本专注于VB.NET编程语言调试...这本手册将提供详细步骤、实例解析和最佳实践,帮助你成为VB.NET调试领域的专家。无论你是初学者还是经验丰富的开发者,这本书都将是你不可或缺的参考资料。

    c#与.NET 3.5高级程序设计源代码 (CSharp.2008.and.the.NET.3.5.Platform)

    8. **并行计算和任务并行库(TPL)**:虽然.NET 4.0才正式引入TPL,但在.NET 3.5 SP1中已有预览版。源代码可能涉及到并发编程和异步任务的实现。 9. **LINQ to SQL**:这是.NET 3.5早期的ORM解决方案,源代码会展示...

    VB.NET案例开发

    本书通过一系列的实例,将理论与实践相结合,帮助读者提升VB.NET编程技能。 首先,VB.NET是.NET框架的一部分,这意味着它能够充分利用.NET提供的服务,如垃圾回收、类型安全和跨语言互操作性。这使得VB.NET开发者...

Global site tag (gtag.js) - Google Analytics