您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 公司方案 > CLR40,VS2010中的并行化
白杨实验室第1页共5页Windows用户CLR4.0,VS2010中的并行化2010-05-03VisualStudio2010是一个大版本。相对于05到08的修正性改动,VS2010和VS2008之间的差异很大。主要的差异在两个方面:“结构化并行”和“动态语言”。我比较关心的是并行,所以简单的浏览了这方面的改进,和大家分享。通过CLR2.0也能够运行多线程程序。也同样可以发挥多核CPU的性能。但是CLR4.0给我们带来的概念是结构化并行.....。什么叫“结构化并行”?参考“结构化程序”这个概念。在“结构化程序”出现之前,程序员使用goto编写各种各样的复杂程序。随着for,while等流程控制关键字,函数,类继承,泛型等结构化概念的逐步提出和完善。在串行程序领域基本实现了“结构化”。同理结构化并行就是通过一组标准的方法编写并行程序。减少并行程序的维护成本。CLR4.0除了在概念上支持了结构化并行,还提供了并行数据结构,轻量级同步等方面提供了新功能。VS2010在调试,测试环节也加入了并行程序的支持。1.结构化并行结构化并行,是一种让程序员更关注并行计算本身,而不是技术层面的并行计算设计思想。在结构化并行中内看不到任何Thread或者ThreadPool字样。各种针对线程的操作都被编译器和TPL(TaskParallelLibrary)封装。使用TPL之后,程序看起来就是Parallel.For,传统for循环的并行版本Parallel.ForEach,传统foreach循环的并行版本Parallel.Inovke,传统Inovke的并行版本没有必要粘贴Parallel.X使用示范,从书写角度看,他们和过去串行代码非常类似。只不过集合中的每个元素并不是被顺序处理,而是被并行处理。如果仅仅是Parallel.X系列,显然不能形成结构化并行体系。另外还有2个特性需要说明并行异常:Parallel计算过程中,尤其是基于数据分割计算的并行计算中。他们每个执行线程执行的代码都是相似的。如果继续沿用传统的异常机制。那么线程概念势必还会出现在结构化并行中,让程序员纠缠在技术细节。CLR4.0提出了AggregateException概念。用于Parallel.X内出现的异常行为。异常被汇总呈现,忽略了线程细节。线程只是手段,并行才是目的。搜索关键字【AggregateException】执行撤销Cancellation:如果某项操作需要花费很长时间,而用户又不想让计算继续。这时用户很可能点“Cancel”按钮撤销执行。执行撤销并不是一定要CLR4.0才能支持。每个程序员都有自己独特的,千奇百怪的执行撤销方法。CLR4.0提供了统一的方法实现执行撤销。不论是传统基于Thread的并行程序,还是基于TPL的并行程序,甚至PLINQ都可以完成执行撤销。搜索关键字【CancellationToken】2.专为并行设计的数据结构白杨实验室第2页共5页Windows用户在CLR1.1中,通过对各种集合对象的同步封装,可以得到一个多线程安全的集合对象。但是这种封装非常简陋。它仅仅保证数据正确性,毫无性能可言。CLR4.0在System.Collections.Concurrent名称空间下提供了若干专为并行设计的数据结构。并行数据结构对应的传统数据结构BlockingCollectionT带有阻塞的ListT,实现生产者-消费者模式的好东西ConcurrentBagTLinkedListTConcurrentDictionaryK,VDictionaryK,VConcurrentQueueTQueueTConcurrentStackTStackT3.轻量级线程同步手段3.1.旋转等待(SpinWait)和旋转锁(SpinLock)SpinWait/Lock是实现无锁数据结构1必备功能。它可以带来比基于内核锁编程更高的吞吐量。如果没有SpinWait,可以采用Thread.Sleep(1)作为替代实现。SpinWait对应CPU的PAUSE指令。而Thread.Sleep(1)需要涉及CPU,中断控制器,定时器,OS线程调度代码等很多器件。可以认为SpinWait的性能千倍于Thread.Sleep(1)。如果在Spinloop内不插入SpinWait。让Spinloop成为一个“死循环”。CPU无法知道这个循环的目的,会进行一些大量没有意义预操作,造成CPU更多的能耗损失。有些资料还认为,不仅是能耗损失,不插入SpinWait,在Spinloop退出时,将产生分支预测错误,让CPU重新填充执行流水线,有些CPU估计会损失大约25个指令周期。如果没有SpinLock,可以采用Interlocked.CompareExchage加for循环实现SpinLock类似功能。但一般来说,基于Interlocked.CompareExchage结构实现的简单SpinLock只适合2个线程之间的同步操作。更多的线程情况效率并不高。不过SpinLock程序看起来更直观。所以在今后的程序中,应该优先使用SpinLock。虽然没有反编译SpinLock代码,但是估计SpinLock的内部实现很可能是MCSLock。或者CLR根据具体服务器CPU的数据决定采用CAS手段(用于2~4Core)还是MCSLock(4+Core)手段。3.2.xxSlim系列ManualResetEvent,Semaphore,ReadWriteLock都是OS的核心对象的封装,管理比较复杂。虽然OS由世界级顶尖程序员花费几十年精心书写的代码。但是由于核心对象在设计上需要具有跨越进程访问的能力,这样OS在访问核心对象时不得不做一些非常耗时的动作:1)在OS代码中验证调用者对核心对象的访问权2)切换内核栈和用户栈3)进出CPU的Ringdoor,可能产生上下文切换和CPU指令解析的流水线断流。1无锁数据结构(Lock-FreeDataStructure),准确的说法应该是无内核锁数据结构。白杨实验室第3页共5页Windows用户这些操作都非常耗时,一般认为核心对象的操作需要花费1000~10000CPU周期。如果同步仅限与同一个进程内,其实并不需要OS核心对象。CLR4.0实现了对应几个轻量级同步对象ManualResetEventSlim,SemaphoreSlim,ReadWriteLockSlim。3.3.Barrier/CountdownEventBarrier:采用WaitHandler也可以实现Barrier的功能。但是仔细对比,发现如果要同步N个线程。WaitHandler需要N个同步对象。而采用Barrier只需要1个对象。而且Barrier代码比WaitHander的代码自我描述性2强。CountdownEvent:CountdownEvent也可以称为反Semaphore。Semaphore初始化阶段定义Semaphore有最大资源数,当计数为0时(即资源不够用时)则阻塞线程。而CountdownEvent在主线程上进行等待,当等所有工作完成后,主线程的Wait方法将不再阻塞。4.调试中的并行化4.1.传统线程列表进行了改良新的线程列表比VS2008用起来舒服:可以让线程分组显示搜索指定线程(SearchCallStack),这功能应该是为了未来“众核”芯片设计的。一般多核程序哪里会有多到让人需要搜索的线程数量线程栈直接显示在线程窗口。不需要和堆栈窗口来回切换。4.2.并行堆栈(ParallelStack)视图在调试程序时往往会查看程序的CallStack。但是CallStack仅仅是单线程内的一个概念。在并行化程序中,传统的CallStack视图不能表达多线程之间的调用关系。在VS2101中有一个ParallelStack调试视图。它可以显示了线程之间的调用关系。2代码不需要另外书写注释,天生具有的描述能力。比如当可以采用if-elseif–elseif…else语句,也可以采用switch–case语句的时候。Switchcase语句的自我描述性就强于if–elseif..else语句。白杨实验室第4页共5页Windows用户5.其他一些实用性小改进可以用DataTips将数据的值显示在界面上,方便调试。还可以监视值标记注释信息代码产生比过去强大许多,可以产生新的类型、属性和方法。旧版VS只能产生新的方法。【Visualizer】,可以自己为了复杂类型设计查看器更多Parse方法具有了TryParse形式。减少不必要的异常产生更多的集合对象被IEnumerableT代替。减少不必要的等待和内存占用。支持Memory-MappedFiles。这种手段是各种多进程数据同步手段的最底层。自然也最快捷。多屏幕支持,将文档从IDE拖拽的另外一个屏幕上,操作手感有些像Chrome6.探讨,一些遗憾6.1.仍然没有支持基于GPU体系结构的并行白杨实验室第5页共5页Windows用户CLR4.0内的各种并行,归根结底仍然是基于Thread的并行手段。虽然CLR4.0提供了很多新的轻量级同步元语。而且Task也让程序看起来有些结构化并行。但CLR4.0并没有实现基于“线程组ThreadGroup”和“波震面wavefront”的真正结构化并行。在CLR4.0中,和线程组最接近的概念应该是Task。但他们有所区别。ThreadGroup可以直接组织成高维结构。比如5维。而Task需要显示的通过多层Parallel.For堆叠组合。ThreadGroup内的各“Thread”通过系统设定的ThreadID找到自己需要计算的数据范围。而Parallel.For需要程序员通过特定的参数指定线程的计算范围。而指定参数的过程是串行的。随着DX11、IE9的发布,GPU在PC中的地位将越来越重要。GPU虽然不能全面代替CPU,但是对于密集计算软件来说,GPU具有百倍性能优势。苹果,谷哥的产品都强化了GPU的使用,微软显然不会坐视。CLR对GPU的支持应该只是时间问题。6.2.AVX支持VS2010的寄存器视图中列出了AVX寄存器。AVX是一组Intel企图让X86CPU带有和GPU一样计算能力的指令集。具有高度的指令并行性,目前第一代AVX只支持256位计算,未来可扩展为512,1024位计算。支持AVX计算器的CPU预计在2011年Intel的SandyBridge或者AMD的FutureBulldozerCPU上支持。而OS需要Win7SP1支持。但它属于90年代SIMD技术的延伸,个人并不看好AVX。6.3.Concurrency和Parallel两个术语搜索关键词:【ConcurrencyParalleldifference】我接触CLR4.0之前我一直认为:Concurrency翻译为并发,描述同一个CPU核通过快速的分时..计算,让程序看起来同时在做两件事情。Parallel翻译为并行,描述多个CPU核同.时.计算。这次CLR4.0的并行数据结构采用Concurrency术语让人非常困惑。更有难以理解的是,CLR4.0在其他并行场合均采用了Parallel术语。
三七文档所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
本文标题:CLR40,VS2010中的并行化
链接地址:https://www.777doc.com/doc-2906071 .html