You'll need Macromedia Flash Player 8 or above in order to view some of our content. Download now!

成功的并行编程

说明一些开发者在为并行系统编程,力求改善工作效率时重复出现的话题。
我是 James Reinders。我曾经四处出差,和程序员讨论并行编程的问题,从中我总结出了几条经验:它们能让程序员更顺利地编写并行程序。

第一条经验是:考虑并行性。我的意思是,首先考虑程序中的并行性。不要先考虑如何以传统方法实现您的程序,然后再试着把并行性硬塞进去。现实情况可能是,您已经有了一些程序,并需要把并行性引入其中。但我还是希望您退一步想想,什么才是真正的并行性,如何获得并行性,然后在忙着写代码之前先制订一个策略。这种方法切实有效,即使您不能马上获得并行性的所有好处。您可以制订一个策略,然后每次引入一点,并制订如何利用它的计划。

第二条经验是,不要根据现有处理器的数量进行编程。您要的考虑的应该是任务、并行程序段和程序工具,但不要考虑线程。我把这称为根据任务编程,而非根据线程编程。通常来说,每个处理器上有一个线程。最好的并行程序不是先问处理器的数量,然后围绕这个数量来编写所有算法。虽然较低的层次上可能存在这种情况,但程序的高层部分应该制造任务——大量任务,然后让一些底层结构把这些任务和处理器的数量联系起来。显然,与一个只能制造两个任务的程序相比,一个能制造数千个并行任务的程序的扩展性要好得多。因此,编程时的重点是任务,而非线程。

第三条不应忽视的经验是:检查自己正在使用的工具。检查编译器、库、调试工具;然后问问自己:这些工具在设计时是否考虑了并行性因素?如果答案是否定的,就找找看有没有其它工具可以使用,同时非常认真的思考一下,以免在并行编程时忽略了适当的工具,从而大大增加工作难度。作为一名专业人士,一名正在为并行性操心的程序员,您的确应该好好检查一下自己正在使用的工具。也许您在编写现在的程序时,习惯寻找对您大有帮助的工具,当您涉足并行编程时,您应该保持这种态度,寻找适合并行编程的工具。

我最喜欢的是第四条经验,因为事实证明这条经验极度重要,我见到人们在并行编程时总是会用到它,但却很少谈到它。这条经验就是,确保您的程序能够顺序运行。如果您有一个多线程程序,它能以四线程、八线程或更多线程运行,请确保它能以单线程运行。单线程运行时的效率并不重要,重要的是,如果您能让程序以单线程运行,您就能在这一模式下完成许多调试工作,因为您可以像调试顺序运行程序一样调试程序中的常见错误,在此过程中无需调试与并行性有关的特殊问题。然后,您可以让它以双线程或四线程运行。如果以四线程运行时程序出现故障,而以单线程运行时故障消失,则说明故障与您处理并行性的方式有关。如果在单线程运行时故障依然存在,则好处是您可以在单线程模式下,用已有的传统调试工具进行调试。人们很容易写出只能以并行方式运行的程序。这是一种不良习惯。应该避免使用强制程序并发运行的编程技巧。一般来说,编写一个能够单线程运行的程序一点也不困难,而这能够大大降低调试的难度。

第五条经验。尽量限制锁的使用。一个常见现象是,一旦人们了解了并行性,了解需要让多个线程保持同步,让程序的执行片断之间保持同步,一旦他们了解了加锁技术,他们就会开始加锁——许许多多的锁。之后他们就会了解加锁带来的弊端。一是效率低下——它们限制了程序的可扩展性。再有就是,在一个不断变化而且需要调用库的程序中,锁和锁之间常常相互干扰并造成死锁,进而产生各种各样的问题。锁越少越好。让我们回到第一条经验——考虑并行性,然后把这两条经验联系起来。如果您时刻提醒自己不要用太多锁,那么,在程序中提取并行性的最佳方法并不需要显性加锁,至少不需要太多。如果您用的算法需要许许多多的锁,致使您到处用锁进行保护,则不妨花点时间考虑一下,能否换一种能大大减少锁的数量的算法,或者是采用隐性同步、完全不需要锁的算法。

还有一条经验是别忘了内存分配。事实证明,在程序的并行化过程中,如果您继续使用以前使用的内存分配技术,则内存分配将变成一个很常见的程序瓶颈。与一个可扩展的内存分配程序相比,使用多个内存池的效率要高得多。市场上有各种各样的内存池出售。这条经验就是,别忘了看看这些内存池。别忘了想一想,您在编程时是否用了很多精力在内存分配上,如果是,那么您在引入并行性的时候,别忘了让内存分配也实现并行。

最后一条经验是,回头想想阿姆达尔定律,以及 Gustafson 在 1988 年就此定律提出的观点。为了真正获得程序的可扩展性,您需要考虑,随着处理器数量的不断增加,随着系统处理能力的增强,工作量也会不断增加,您应该记住,您要从中获得性能提升。如果换个角度看这条经验,结果就是:就今天的程序和数据集而言,对速度的提升不要期望太高。应该把可扩展性作为目标。您可以在现有处理器上获得一定程度的性能提升,但一定要好好想想,随着工作量的增加,您如何实现扩展。将来,您的程序需要处理更多数据,或者完成更多任务。因此,应随时把可扩展性放在心上。以上就是我要说的七条经验,在我看来,它们对今天从事并行编程的人很有帮助。

多核处理器有前途吗?

了解多核处理器的功耗、内存和并行指令集。

了解任务和数据并行

任务和数据并行之间的差异,以及如何避免阿姆达尔定律施加的限制。

必须了解的三个并行问题

英特尔James Reinders称,在管理多核系统方面,可扩展性、正确性和可维护性全都是至关重要的因素。

并行之抽象方法

处理原始线程是并行应该避免的问题之一。抽象化为解决这个问题提供了一种方法……

成功的并行编程

说明一些开发者在为并行系统编程,力求改善工作效率时重复出现的话题。

并行编程基础:第一部分

了解线程构造块的核心算法——一个并行编程C++模板库。

并行编程基础:第二部分

英特尔的James Reinders深入探究线程建构基础——一个并行编程C++模板库。

并行编程之API

英特尔James Reinders解释消息传递接口(MPI)——一个并行API。

About Us | Contact Us | Membership | RSS Feeds
Privacy Policy | Terms of Use

Copyright © 2007 CNET Networks, Inc. All rights reserved.

Other CNET Networks sites: ZDNet Australia | CNET.com.au | AppleSource
Builder.com | Builder UK | TechRepublic