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

并行编程基础:第二部分

英特尔的James Reinders深入探究线程建构基础——一个并行编程C++模板库。
大家好,我是 James Reinders。今天我们继续学习线程构建模块的第 2 部分。作为 1 种 C++ 模板库,线程构建模块可满足我们构建应用程序的所有需要,并可使由 C++ 写成的应用程序以并行方式运行。接下来我将为大家介绍线程构建模块的其它知识,有些地方将稍加扩展。加上我们先前介绍的算法,即完成了对线程构建模块的学习。

如前所述,您可以把线程构建模块看成可满足您任何需要的完整程序包,不过随着我们进一步学习,您会发现,在和实现并行性的其它方式一同使用时,有些东西非常有用。 因此,您既可以使用整个程序包,也可以只使用其中的某些部分。

为了提供更多背景知识,而不只是泛泛介绍线程构建模块的内容,我将尝试深入讲解与这些程序包所解决的某些复杂问题有关的知识点,说明为什么在解决这些问题时,使用线程构建模块这样的软件包比试图自行解决效果更好。

除算法外,线程构建模块还有其它 5 大特性:
(i) 容器——本例中为高并发容器。容器可存放数据,在并行程序中能被不同的线程访问。
(ii) 一个可扩展的内存分配程序——同样,它只是一个内存分配程序,被设计为可由多个线程处理。
(iii) 互斥
(iv) 计时功能
(v) 在线程构建模块中自行访问任务计划程序,实现更高级的功能。

我们在第 1 部分讨论的模板其实都是通过调用“任务计划程序”实现的。

我们先来看看“容器”。线程构建模块提供 3 种不同的容器。即“队列”、“矢量”和“hash”表。在 STL 中同样提供这些内容,不过 STL 提供的不是线程安全的版本。本例中,队列、向量和 Has h图都可被访问。他们拥有同样的 API 和同样的设计,实现方式也一样,都是可被多个线程并发使用。为了增加趣味性,我们来看看队列的并发实现,相对来说似乎这比较简单,不过这会产生一个著名的“ABA 问题”。这会在使用某些简单的东西,如用 compare 和 swap 等原子操作实现队列时发生,而且事实上这里面仍然有一些问题。

因此,如果考虑到为了保证能并发使用而必须做到的那些事情,队列其实是非常复杂的。这有两个有趣的问题值得玩味,即 ABA 问题以及如何实现一个队列。经过仔细研究后,我意识到我宁愿使用别人已经写好的容器也不愿自行解决这两个问题。

“可扩展的内存分配程序”。在考虑自行实现时,或许这是最简单的一个。不过当你深入了解其细节,了解到它是如何高效实现,如何创建线程池,使多个线程能够同时分配和释放内存而无需分批实现,如何补偿高速缓存行,确保各对象之间相互距离足够远,不会出现误共享时,情况就不是这样了。可扩展的内存分配程序并非像其表面这么简单。您真正想做的其实只是能够调用一个 malloc 函数,能够使用和关注 new 和 delete,可扩展的内存分配程序让您能实现这些功能。我们来看看在 C++ 程序中使用可扩展的 malloc、new 和 delete 功能的情形。这是一个非常棒的特性,值得我们关注。每一个都能独立使用,因此不必全都用上。

为了实现可移植性,线程构建模块还定义了“互斥”。如此一来,在多个线程访问同一数据时,一个线程在自身结束前能够拒绝其它线程实施修改。这里有两种类型的互斥。第一种是传统的“锁”和“解锁”。另一种是“原子操作”(同时结束但保证能一起发生的操作)。

使用线程构建模块所定义的互斥的真正价值在于他们可移植。只需编程 1 次,就可分别编译为在多个不同的平台上运行(可轻松移植到 Windows、Linux、Mac OS10 及其它多个平台上而无需修改程序)。

“计时”。这并非是一项关键特性,不过我想每个人都想拥有这项特性,因为这样就能确定当前和稍后的时间,将这两个时间相减即可算出程序运行了多长时间。借助线程安全版本的定时特性,可实现更佳的粒度,即使线程在多个处理器上重新调度过也值得信赖,尽管会稍微复杂一些,在线程构建模块中定义了此特性真的是一件很棒的事情。

最后我们来看一下线程构建模块真正重要的内容——“任务计划程序”。我们在第一部分讨论过的算法都与任务的定义有关。无论是 parallel_for、reduce 或可用的操作/算法,最终都是创建大量任务。然后任务计划程序将把任务映射到各个线程即各个处理器上,应用程序也得以运行。事实上,我们可把任务计划程序称为“非抢占非公平式计划程序”。它使用了一些非常高级的算法来平衡多个处理器的负载。即使系统中各处理器的性能不尽相同,或者不同的应用分别运行在各处理器上,任务计划程序所能实现的负载平衡也是非常复杂的。它能帮您尽可能快地运行程序。

以上就是除了我们在第一部分讨论过的算法以外,线程构建模块的五大特性。 如想了解更多信息,可登录 www.threadingbuildingblocks.org,下载此软件和相关文档。

多核处理器有前途吗?

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

了解任务和数据并行

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

必须了解的三个并行问题

英特尔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