英特尔(R) 线程构建模块
入门指南
“英特尔® 线程构建模块”是针对使用线程的 C++ 代码的、基于运行时的并行编程模型。它由基
于模板的运行时库组成,可帮助充分利用多核处理器的潜在性能。使用“英特尔® 线程构建模块”
可以编写具有以下特点的可伸缩应用程序:
• 指定任务而不是线程
• 强调数据并行编程
• 利用并发采集与并行算法
本指南提供一个使用“英特尔® 线程构建模块”来编写、编译、链接及运行并行应用程序的完整示
例。该示例演示如何去探索函数库的关键功能,及成功构建与链接应用程序。阅读完本指南之后,
您应该可以使用“英特尔® 线程构建模块”来编写与构建自己的代码。
目录
免责声明与法律信息 .................................................................................................................2
1
2
3
4
5
6
注意默认目录路径 ................................................................................................3
注册环境变量(仅限 Linux* 与 Mac OS*)................................................................4
使用 parallel_for 开发应用程序 ..............................................................................5
构建应用程序 .....................................................................................................9
运行应用程序 ...................................................................................................11
后续步骤.........................................................................................................12
英特尔(R) 线程构建模块
免责声明与法律信息
本文所含信息专门针对英特尔® 产品提供。本文并未授予任何知识产权的许可证,无论是明确、暗示、禁止翻供还是其它任何形式。除这些产品的
“英特尔销售条款”之规定外,英特尔概不承担任何其它义务,对于英特尔产品的销售与/或使用(包括适合特定用途、适销性或不侵犯任何专利权、
版权或其它知识产权),英特尔不作任何明确或暗示的担保,也不承担任何赔偿责任。英特尔产品无意用于医疗、救生、维持生命、危急控制、安全
系统或核设施等用途。
英特尔随时可能更改技术规格与产品说明,如确有更改,恕不另行通知。
标有“保留”或“未定义”字样的任何功能或指令,其存在性与特性均不确定,设计人员切勿对此有所依赖。英特尔保留这些供将来定义之用,对于
因将来对它们的更改而导致的任何冲突或不兼容现象,英特尔概不承担任何责任。
MPEG 是 ISO 推行的视频压缩/解压缩国际标准。MPEG 编解码器的实现或是支持 MPEG 的平台可能需要从包括英特尔公司在内的多家实体获取许
可证。
本文所述的软件可能包含一些软件缺陷,导致产品与发布的规格不符。目前已确定的软件缺陷可应客户要求提供。
本文及其所述软件均以许可证为前提而提供,只能依据许可证的各项条款进行使用或复制。本手册中的信息仅供参考之用,可随时更改而不另行通
知,亦不得视为英特尔公司所作的任何承诺。对于本文或提供的与本文有关的任何软件中可能出现的任何错误或不准确之处,英特尔公司概不承担任
何责任或义务。
除此类许可证允许的内容之外,未经英特尔公司书面明确同意,对于本文的任何部分,均不得以任何形式或通过任何手段进行复制或传输,亦不得将
其存储到检索系统中。
标有“保留”或“未定义”字样的任何功能或指令,其存在性与特性均不确定,开发人员切勿对此有所依赖。开发人员的软件代码如果不恰当地使用
了保留的或未定义的功能或指令,在英特尔处理器上运行时,可能会导致无法预知的行为或故障。英特尔保留这些功能或指令供将来定义之用,对于
因按照未授权的方式使用它们而引起的任何冲突或不兼容现象,英特尔概不承担任何责任。
BunnyPeople、赛扬、Celeron Inside、迅驰、迅驰徽标、Core Inside、FlashFile、i960、InstantIP、英特尔、英特尔徽标、Intel386、
Intel486、Intel740、IntelDX2、IntelDX4、IntelSX2、英特尔酷睿、Intel Inside、Intel Inside 徽标、“英特尔。超越未来。”、“英特尔。
超越未来。”徽标、Intel NetBurst、Intel NetMerge、英特尔网擎、Intel SingleDriver、Intel SpeedStep、Intel StrataFlash、英特尔欢
跃、英特尔博锐、Intel XScale、IPLink、安腾、Itanium Inside、MCS、MMX、Oplus、OverDrive、PDCharm、奔腾、Pentium Inside、
skoool、Sound Mark、The Journey Inside、VTune、至强以及 Xeon Inside 是英特尔公司或其子公司在美国以及其它国家或地区的商标或注
册商标。
* 其它品名与品牌可能是属于其它公司的资产。
© 2005–2007 英特尔公司版权所有。
修订历史
文档编号
修订版编号
说明
314904-001
001
应用了新的模板。
修订日期
2006 年 8 月
2
文档编号:314904-001CN
注意默认目录路径
1 注意默认目录路径
开始之前,确保在机器上已经成功安装“英特尔® 线程构建模块”。否则请根据 INSTALL.txt 中
的操作说明进行安装。
本文中使用的 bin、doc 及 examples 目录的默认位置如下表所示:
默认目录
/opt/intel/tbb/2.0/[bin|doc|examples]
/Library/Frameworks/Intel_TBB.framework/Versions/2.0/[bin|doc|examples]
C:\Program Files\Intel\TBB\2.0\[doc|examples]
C:\Program Files (x86)\Intel\TBB\2.0\[doc|examples]
平台
Linux∗
Mac OS∗
采用英特尔®
IA-32 处理器的
Windows∗
采用 Intel® 64
指令集体系结构
(ISA) 的
Windows∗
入门指南
3
英特尔(R) 线程构建模块
2 注册环境变量
(仅限 Linux* 与 Mac OS*)
使用“英特尔® 线程构建模块”之前,必须注册一些环境变量,这些变量用于确定必需的函数库及
include 文件的位置,具体如下:
1. 确定操作系统配置脚本的位置。这些脚本位于 bin 目录。
2. 执行适合具体操作系统的脚本。在 Linux* 与 Mac OS* 系统上,从 bin 目录对
tbbvars.[c]sh 脚本使用 source 命令。这些脚本修改 LD_LIBRARY_PATH、
DYLD_LIBRARY_PATH (Mac OS) 及 CPATH 变量保存的路径,并且只影响当前外壳。
4
文档编号:314904-001CN
使用 parallel_for 开发应用程序
3 使用 parallel_for 开发应用程序
本节介绍在子字符串匹配程序中使用 parallel_for 模板的一个基本示例。对于字符串中的每个
位置,该程序都显示字符串其它部分的最大匹配子字符串的长度与位置。
以 “babba” 字符串为例。从位置 0 开始,“ba” 是与字符串的其它部分(位置 3)匹配的最大子字
符串。
在“英特尔® 线程构建模块”的 examples/GettingStarted 文件夹中,您可以看到此程序的完
整版。或者,您也可以按照这里提供的信息,一步一步地来开发这个应用程序。在本节中,每个步
骤中添加的新代码都显示为蓝色。续接上一个步骤的代码显示为黑色。所有的行都按照它们在最终
的完整示例中出现的顺序进行编号。
要开发示例代码:
1. 创建一个新的空白应用程序。
在主函数中,通过实例化 task_scheduler_init 对象(第 37 行)来初始化任务调度程
序。
⎯ 使用“英特尔® 线程构建模块”算法的任何线程都必须包含一个已初始化的
task_scheduler_init 对象。在本例中,task_scheduler_init 对象的默认构造器
向任务调度程序通知线程将要参与到任务的执行中,而析构器则向调度程序通知线程不再
需要调度程序。
⎯ task_scheduler_init 类的定义是从 task_scheduler_init.h 头文件(第 04
行)中包含进来的。
⎯ using 语句导入 tbb 名称空间,在其中可以找到函数库中所有的类与函数(第 07
行)。
04: #include “tbb/task_scheduler_init.h”
07: using namespace tbb;
36: int main() {
37: task_scheduler_init init;
47: return 0;
48: }
2. 创建要由程序(第 38 至 40 行)转换的示例字符串,并创建一些数组以保存最大匹配子字符
串的长度及其位置(第 41 至 42 行)。
本例生成由一系列的 'a’ 与 'b’ 字符组成的斐波纳契字符串。
入门指南
5
英特尔(R) 线程构建模块
3. 添加一些语句,以输出每个位置上匹配的最大子字符串的长度与位置(第 45 至 46 行)。
01:
02:
04:
07:
08:
09:
36:
37:
38:
39:
40:
41:
42:
43–44:
45:
46:
47:
48:
#include
#include
#include "tbb/task_scheduler_init.h"
using namespace tbb;
using namespace std;
static const size_t N = 23;
int main() {
task_scheduler_init init;
string str[N] = { string("a"), string("b") };
for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2];
string &to_scan = str[N-1];
size_t *max = new size_t[to_scan.size()];
size_t *pos = new size_t[to_scan.size()];
// will add code to populate max and pos here
for (size_t i = 0; i < to_scan.size(); ++i)
cout << " " << max[i] << "(" << pos[i] << ")" << endl;
return 0;
}
4. 添加一个对 parallel_for 模板函数的调用(第 43 至 44 行)。
该调用的第一个参数是描述迭代空间的 blocked_range 对象。
blocked_range 是由“英特尔® 线程构建模块”库提供的一个模板类。构造器包含三个参
数:
⎯ 范围的下限。
⎯ 范围的上限。
⎯ 。parallel_for 又将该范围分为多个子范围,其中包含约
个元素。
parallel_for 函数的第二个参数是要应用于每个子范围的函数对象。
01:
02:
04:
05:
06:
07:
08:
09:
#include
#include
#include “tbb/task_scheduler_init.h”
#include “tbb/parallel_for.h”
#include “tbb/blocked_range.h”
using namespace tbb;
using namespace std;
static const size_t N = 23;
6
文档编号:314904-001CN
使用 parallel_for 开发应用程序
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
int main() {
task_scheduler_init init;
string str[N] = { string(”a”), string(”b”) };
for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2];
string &to_scan = str[N-1];
size_t *max = new size_t[to_scan.size()];
size_t *pos = new size_t[to_scan.size()];
parallel_for(blocked_range
(0, to_scan.size(), 100),
SubStringFinder( to_scan, max, pos ) );
for (size_t I = 0; I < to_scan.size(); ++i)
cout << ” ” << max[i] << ”(” << pos[i] << ”)” << endl;
return 0;
}
5. 实现 parallel_for 循环体(第 10 至 35 行)。
在运行时,parallel_for 模板自动将范围分为多个子范围,并在每个子范围上激活
SubStringFinder 函数对象。
6. 定义 SubStringFinder 类(第 10 行),以填充在给定的子范围中找到的 max 与 pos 数
组元素。
在第 16 行,r.begin() 调用返回子范围的起始位置,r.end() 方法返回子范围的结束位
置。
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
#include
#include
#include
#include “tbb/task_scheduler_init.h”
#include “tbb/parallel_for.h”
#include “tbb/blocked_range.h”
using namespace tbb;
using namespace std;
static const size_t N = 23;
class SubStringFinder {
const string str;
size_t *max_array;
size_t *pos_array;
public:
void operator() ( const blocked_range& r ) const {
for ( size_t I = r.begin(); I != r.end(); ++I ) {
size_t max_size = 0, max_pos = 0;
for (size_t j = 0; j < str.size(); ++j)
if (j != i) {
13:
14:
15:
16:
17:
18:
19:
入门指南
7
英特尔(R) 线程构建模块
20:
21:
22:
23:
24:
25:
26:
27:
28:
size_t limit = str.size()-max(I,j);
for (size_t k = 0; k < limit; ++k) {
if (str[I + k] != str[j + k]) break;
if (k > max_size) {
max_size = k;
max_pos = j;
}
}
}
29:
30:
31:
32:
33:
34:
35:
36–48: // The function main starting at line 36 goes here
max_array[i] = max_size;
pos_array[i] = max_pos;
}
}
SubStringFinder(string &s, size_t *m, size_t *p) :
str(s), max_array(m), pos_array(p) { }
};
8
文档编号:314904-001CN