1. TBB簡介
TBB ( Thread Building Blocks, 線程構建模塊) 是Intel公司開發的並行編程開發的工具。它支持Windows,OS X, Linux平台,支持的編譯器有Visual C++ (version 8.0 or higher, on Windows only), Intel C++ Compiler (version 11.1 or higher) or the GNU Compiler Collection (gcc).
TBB is a collection of components for parallel programming:
- Basic algorithms: parallel_for, parallel_reduce, parallel_scan
- Advanced algorithms: parallel_while, parallel_do, parallel_pipeline, parallel_sort
- Containers: concurrent_queue, concurrent_priority_queue, concurrent_vector, concurrent_hash_map
- Scalable memory allocation: scalable_malloc, scalable_free, scalable_realloc, scalable_calloc, scalable_allocator, cache_aligned_allocator
- Mutual exclusion: mutex, spin_mutex, queuing_mutex, spin_rw_mutex, queuing_rw_mutex, recursive_mutex
- Atomic operations: fetch_and_add, fetch_and_increment, fetch_and_decrement, compare_and_swap, fetch_and_store
- Timing: portable fine grained global time stamp
- Task Scheduler: direct access to control the creation and activation of tasks
2. 應用場景
- 數據包處理: 如 network router emulator
- 圖像處理,和OPENCV,IPP一塊使用,如 IPP with TBB
- 任何可並行的地方
3. 配置
1. 下載地址:https://www.threadingbuildingblocks.org/download
下載:windows release版tbb43_20150424oss_win.zip - 配置環境變量PATH,保證運行時找到dll - 在TBB應用工程中添加tbb包含目錄,即tbb相關頭文件 - 在TBB應用工程中添加tbb庫目錄,即tbb的lib文件,注意32位和64位有分別的目錄
4. 實例
問題:查找一個范圍內的所有素數,子問題是判斷一個數是不是素數,而且每個數字的判斷互不影響,所以可以用並行算法。
find_prime.cc
/* ** find_prime.cc ** g++ find_prime.cc -ltbb -lrt -o find_prime ** -ltbb for tbb library ** -lrt for tbb::tick_count::now() using clock_gettime() */ #include<iostream> #include<tbb/tbb.h> using namespace std; using namespace tbb; int is_prime(int x) { int i; if (x <= 1) { /*1不是質數,且不考慮負整數與0,故輸入x<=1時輸出為假 */ return 0; } for (i = 2; i * i <= x; ++i) { if (x % i == 0) { /*若整除時輸出為假,否則輸出為真 */ return 0; } } return 1; } class FindPrime { public: void operator() (const blocked_range < size_t > &r)const { for (size_t i = r.begin(); i != r.end(); ++i) { if (is_prime(i)) { cout << i << endl; } } } }; int main(int argc, char *argv[]) { size_t end = 100; if (argc > 1 && atoi(argv[1]) > 0) { end = atoi(argv[1]); } parallel_for(blocked_range < size_t > (0, end), FindPrime()); return 0; }
編譯
g++ find_prime.cc -ltbb -lrt -o find_prime
5. C++相關特性
0. operator overloading
parallel_for第二參數是一個類A的實例對象,該類A要重載操作符 ()
.
對於
class Test{ public: void operator()(const int &i) const{ cout<<"operation with i" <<endl; } }; 第一個const保證i不被改變,第二個const保證調用對象不被改變。 使用方法 Test t; t(110);
1. lambda表達式
匿名函數在C++11中引用,語法是
[capture子句](參數列表)mutable throw() -> int{函數體}
最簡單的一個例子,沒有參數,沒有異常處理,沒有返回類型(自動推斷)
[]{cout<<"hello world from lambda!"<<endl;}();
最后的 ()
是對匿名函數的調用,分開來看是這樣的,首先定義一個函數指針
typedef void (*func)(); func f = []{cout<<"hello world from lambda!"<<endl;}; f();
capture子句主要有兩個符號 =
, &
, =
表示以傳值的方式傳遞參數, &
表示以引用的方式(傳地址)傳遞參數,這兩個符號可以單獨使用,也可以組合使用, &
后面還可以跟一個變量,只修飾它。
[] // 沒有定義任何變數。使用未定義變數會導致錯誤。 [x, &y] // x以傳值方式傳入(預設),y以傳地址方式傳入。 [&] // 任何被使用到的外部變數皆隱式地以地址方式加以引用。 [=] // 任何被使用到的外部變數皆隱式地以傳值方式加以引用。 [&, x] // x顯示地以傳值方式加以引用。其餘變數以地址方式加以引用。 [=, &z] // z顯示地以地址方式加以引用。其餘變數以傳值方式加以引用。
2. placement new
所謂placement new就是在用戶指定的內存位置上構建新的對象,這個構建過程不需要額外分配內存,只需要調用對象的構造函數即可。
Task Scheduler
庫會用到這一特性
#include <iostream> #include "tbb/tbb.h" using namespace tbb; using namespace std; class first_task:public task { public: task * execute() { cout << "Hello World!\n"; return NULL; } }; int main() { task_scheduler_init init(task_scheduler_init::automatic); first_task & f1 = *new(tbb::task::allocate_root())first_task(); tbb::task::spawn_root_and_wait(f1); return 0; }
endl;
參考博客:http://www.tuicool.com/articles/R3uu22