C++ OpenMP、TBB库的简单使用


1.OpenMP的简单使用

OpenMP可以用来并行计算for循环,提高程序运行速度。

首先要打开OpenMP支持:“配置属性”——“C/C++”——“语言”——“1.OpenMP支持”后选择“是”。

1 p_get_num_procs() //获取系统中处理器的个数 2 p_set_num_threads(num_count) //设置线程数 3 p_get_thread_num() //获取当前线程的Id号

用法1:

1 #pragma p parallel 2 6 //指定执行代码块的线程数 7 p_set_num_threads(4);//设置线程数,需要包含头文件<p.h> 8 #pragma p parallel 9 或者 10 #pragma p parallel num_threads(4)//在parallel后直接增加线程子句 11

例子1:

1 #include <iostream> 2 #include "p.h" 3 using namespace std; 4 int main() 5 12 system("pause"); 13 return 0; 14 }

从运行结果可以看出,各线程的先后顺序不确定(0是主线程)。

用法2:

1 #pragma p parallel for num_threads(4) 2 for( ; ; ) 3 6 或 7 #pragma p parallel 8 14 }

例子2.

1 #include <iostream> 2 #include "p.h" 3 using namespace std; 4 int main() 5 12 system("pause"); 13 return 0; 14 }

运行结果:

for循环执行的先后顺序不能保证,因此for循环里的内容必须不存在依赖关系。for循环中不能有break和return退出出口。

数据同步问题:

例3.

1 #include <iostream> 2 #include "p.h" 3 using namespace std; 4 int main() 5 16 } 17 cout << " sum = " << sum << endl; 18 system("pause"); 19 return 0; 20 }

正确答案应为10000,但运行时每次得到的结果都不同,这是因为sum变量是每个线程共享的,多个线程同时对sum操作,会因为数据同步问题发生错误。

解决方法:

方法一:对操作共享变量的代码段做同步标识

1 int main() 2 14 } 15 }

方法二:每个线程拷贝一份sum变量,退出并行块时再把各个线程的sum相加

1 #pragma p parallel 2 8 } 9 }

2.TBB库的简单使用
TBB(Thread Building Blocks)是英特尔发布的一个C++标准库。

1.配置

设置环境变量:将tbb中bin文件夹下的vc12(与VS2013对应)的路径添加到环境变量,然后重启电脑。

将include文件夹所在路径添加到包含目录,将lib文件夹所在路径添加到库目录。

2.parallel_for的用法

包含头文件#include ”tbb/parallel_for.h“

**parallel_for(range, body, partitioner)提供了并行迭代的泛型形式。它表示在区域的每个值,并行执行body。partitioner选项指定了分割策略。

例子:

1 #include <iostream> 2 #include <tbb/tbb.h> 3 using namespace std; 4 using namespace tbb; 5 typedef vector<int>::iterator IntVecIt; 6 struct body 7 15 }; 16 int main() 17

使用lambda表达式,上面的例子可以写为

1 int main() 2 11 ); 12 system("pause"); 13 return 0; 14 }

为了更紧凑,对于在一个整形的连续区域执行并行循环,TBB有对应形式的 parallel_for 。表达式 parallel_for(first,last,step,f) 就像 for(auto i = first; i< last; i+= step) f(i)

3.运行时间对比

1 #include <iostream> 2 #include <time.h> 3 void test() 4 9 int main() 10 20 //tbb多线程 21 parallel_for(blocked_range<size_t>(0, 8), [&](const blocked_range<size_t> &i));

对于上面这个例子,调用8次test函数,不使用多线程的运行时间为1333ms,使用OpenMP多线程后的运行时间为196ms,使用tbb多线程后的运行时间为203ms。可以看出使用OpenMP和tbb后程序运行时间加快了好几倍。

3.thread多线程的简单使用
包含头文件#include

创建多线程

1 void func01() 2 5 6 void func02(int num) 7 10 int main() 11 18 19 //线程互斥 20 #include <iostream> 21 #include <thread> 22 #include <Windows.h> 23 #include <mutex>// mutex类的使用需要包含该头文件 24 using namespace std; 25 mutex mu; //线程互斥对象 26 27 int totalNum = 100; 28 29 void thread01() 30 39 } 40 void thread02() 41 50 } 51 52 int main() 53 60 61 //在类外部为类的成员函数创建子线程 62 class Test 69 private: 70 int a=1; 71 int b=2; 72 int c=0; 73 }; 74 int main() 75

4.lambda表达式

lambda表达式是C++11引入的新特性,功能:定义并创建匿名函数对象,以简化编程工作。

语法:[捕获子句](参数列表)mutable关键字 异常关键字 —>返回类型 (实参)

  1. 捕获子句([]是lambda表达式的先导符号,告诉编译器下面是lambda表达式)

  2. 参数列表(可选)

  3. mutable关键字(可选)

  4. 异常关键字(可选)

  5. 返回类型(可选)(省略返回类型时,>也要省略)

  6. lambda函数体

1 int num = [](int num)>int(10);//10是传递的实参 2 cout << num << endl;//打印结果为11

如果想在lambda表达式内访问外部的数据,可使用以下方式传递变量:

1 [=]//值传递所有变量 2 [&]//引用所有变量 3 [var]//值传递变量 4 [&var]//引用传递变量

例子

1 int num = 10; 2 [=]()mutable //当使用mutable关键字时,可以对值传递的变量进行“写”操作 3 ();//此处的小括号不能省略 4 cout << num << endl; //调用lambda后num任然是10(值传递) 5 6 //写成函数的形式 7 auto fun = [=](int a)mutable >int ;//auto关键字自动推断lambda表达式的类型 8 cout << fun(num) << endl;

2.

1 如果想在lambda表达式内访问外部的数据,可使用以下方式传递变量: 2 3 ```c++ 4 [=]//值传递所有变量 5 [&]//引用所有变量 6 [var]//值传递变量 7 [&var]//引用传递变量

例子

1 int num = 10; 2 [=]()mutable //当使用mutable关键字时,可以对值传递的变量进行“写”操作 3 ();//此处的小括号不能省略 4 cout << num << endl; //调用lambda后num任然是10(值传递) 5 6 //写成函数的形式 7 auto fun = [=](int a)mutable >int ;//auto关键字自动推断lambda表达式的类型 8 cout << fun(num) << endl;




上一篇:C++ Windows.h max宏与std::max冲突问题解决

下一篇:Exiv2库的使用(C++)


C/C&#x2B;&#x2B; OpenMP TBB
Copyright © 2002-2019 k262电脑网 www.k262.cn 皖ICP备2020016292号
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!QQ:251442993 热门搜索 网站地图