九九热这里直有精品,1区二区三区在线播放,玖玖爱在线观看资源,国产aⅴ综合网,午夜福利男女,日本亚洲欧美三级,日韩无码黄色导航,内射少妇13区,中文字幕高清网

您身邊的軟件定制專(zhuān)家--9年開(kāi)發(fā)經(jīng)驗(yàn)為您護(hù)航

18678812288
0531-88887250

c++并行計(jì)算庫(kù)TBB和PPL的基本用法

文章作者:濟(jì)南軟件開(kāi)發(fā) 時(shí)間:2016年09月28日

并行庫(kù)充分利用多核的優(yōu)勢(shì),通過(guò)并行運(yùn)算提高程序效率,本文主要介紹c++中兩個(gè)知名的并行庫(kù),一個(gè)是intel開(kāi)發(fā)的TBB,一個(gè)是微軟開(kāi)發(fā)的PPL。本文只介紹其基本的常用用法:并行算法和任務(wù)。

 

TBB(Intel? Threading Building Blocks )

TBB是intel用標(biāo)準(zhǔn)c++寫(xiě)的一個(gè)開(kāi)源的并行計(jì)算庫(kù)。它的目的是提升數(shù)據(jù)并行計(jì)算的能力,可以在他的官網(wǎng)上下載最新的庫(kù)和文檔。TBB主要功能:

 

并行算法

任務(wù)調(diào)度

并行容器

同步原語(yǔ)

內(nèi)存分配器

TBB并行算法

 

parallel_for:并行方式遍歷一個(gè)區(qū)間。

 

parallel_for(1, 20000, [](int i){cout << i << endl; });

parallel_for(blocked_range<size_t>(0, 20000), [](blocked_range<size_t>& r)

{

    for (size_t i = r.begin(); i != r.end(); ++i)

        cout << i << endl; 

});

parallel_do和parallel_for_each:將算法應(yīng)用于一個(gè)區(qū)間

 

vector<size_t> v;

parallel_do(v.begin(), v.end(), [](size_t i){cout << i << endl; });

parallel_for_each(v.begin(), v.end(), [](size_t i){cout << i << endl; });

 parallel_reduce

 

  類(lèi)似于map_reduce,但是有區(qū)別。它先將區(qū)間自動(dòng)分組,對(duì)每個(gè)分組進(jìn)行聚合(accumulate)計(jì)算,每組得到一個(gè)結(jié)果,最后將各組的結(jié)果進(jìn)行匯聚(reduce)。這個(gè)算法稍微復(fù)雜一點(diǎn),parallel_reduce(range,identity,func,reduction),第一個(gè)參數(shù)是區(qū)間范圍,第二個(gè)參數(shù)是計(jì)算的初始值,第三個(gè)參數(shù)是聚合函數(shù),第四個(gè)參數(shù)是匯聚參數(shù)。

 

復(fù)制代碼

float ParallelSum(float array [], size_t n) {

    return parallel_reduce(

        blocked_range<float*>(array, array + n),

        0.f,

        [](const blocked_range<float*>& r, float value)->float {

            return std::accumulate(r.begin(), r.end(), value);

    },

        std::plus<float>()

        );

}

復(fù)制代碼

這個(gè)對(duì)數(shù)組求和的例子就是先自動(dòng)分組然后對(duì)各組中的元素進(jìn)行聚合累加,最后將各組結(jié)果匯聚相加。

 

parallel_pipeline:并行的管道過(guò)濾器

 

  數(shù)據(jù)流經(jīng)過(guò)一個(gè)管道,在數(shù)據(jù)流動(dòng)的過(guò)程中依次要經(jīng)過(guò)一些過(guò)濾器的處理,其中有些過(guò)濾器可能會(huì)并行處理數(shù)據(jù),這時(shí)就可以用到并行的管道過(guò)濾器。舉一個(gè)例子,比如我要讀入一個(gè)文件,先將文件中的數(shù)字提取出來(lái),再將提取出來(lái)的數(shù)字做一個(gè)轉(zhuǎn)換,最后將轉(zhuǎn)換后的數(shù)字輸出到另外一個(gè)文件中。其中讀文件和輸出文件不能并興去做,但是中間數(shù)字轉(zhuǎn)換的環(huán)節(jié)可以并行去做的。parallel_pipeline的原型:

 

parallel_pipeline( max_number_of_live_tokens, 

                   make_filter<void,I1>(mode0,g0) &

                   make_filter<I1,I2>(mode1,g1) &

                   make_filter<I2,I3>(mode2,g2) &

                   ... 

                   make_filter<In,void>(moden,gn) );

  第一個(gè)參數(shù)是最大的并行數(shù),我們可以通過(guò)&連接多個(gè)filter,這些filter是順序執(zhí)行的,前一個(gè)filter的輸出是下一個(gè)filter的輸入。

 

復(fù)制代碼

float RootMeanSquare( float* first, float* last ) {

    float sum=0;

    parallel_pipeline( /*max_number_of_live_token=*/16,       

        make_filter<void,float*>(

            filter::serial,

            [&](flow_control& fc)-> float*{

                if( first<last ) {

                    return first++;

                 } else {

                    fc.stop();

                    return NULL;

                }

            }    

        ) &

        make_filter<float*,float>(

            filter::parallel,

            [](float* p){return (*p)*(*p);} 

        ) &

        make_filter<float,void>(

            filter::serial,

            [&](float x) {sum+=x;}

        )

    );

    return sqrt(sum);

}

復(fù)制代碼

  第一個(gè)filter生成數(shù)據(jù)(如從文件中讀取數(shù)據(jù)等),第二個(gè)filter對(duì)產(chǎn)生的數(shù)據(jù)進(jìn)行轉(zhuǎn)換,第三個(gè)filter是對(duì)轉(zhuǎn)換后的數(shù)據(jù)做累加。其中第二個(gè)filter是可以并行處理的,通過(guò)filter::parallel來(lái)指定其處理模式。

 

parallel_sort:并行排序

 

const int N = 1000000;

float a[N];

float b[N];

parallel_sort(a, a + N);

parallel_sort(b, b + N, std::greater<float>());

parallel_invoke:并行調(diào)用,并行調(diào)用多個(gè)函數(shù)

 

void f();

extern void bar(int);

 

void RunFunctionsInParallel() {

    tbb::parallel_invoke(f, []{bar(2);}, []{bar(3);} );

}

TBB任務(wù)

task_group表示可以等待或者取消的任務(wù)集合

 

task_group g;

g.run([]{TestPrint(); });

g.run([]{TestPrint(); });

g.run([]{TestPrint(); });

g.wait();

 

 

PPL(Parallel Patterns Library)

  PPL是微軟開(kāi)發(fā)的并行計(jì)算庫(kù),它的功能和TBB是差不多的,但是PPL只能在windows上使用。二者在并行算法的使用上基本上是一樣的, 但還是有差異的。二者的差異:

 

parallel_reduce的原型有些不同,PPL的paraller_reduce函數(shù)多一個(gè)參數(shù),原型為parallel_reduce(begin,end,identity,func,reduction), 比tbb多了一個(gè)參數(shù),但是表達(dá)的意思差不多,一個(gè)是區(qū)間,一個(gè)是區(qū)間迭代器。

PPL中沒(méi)有parallel_pipeline接口。

TBB的task沒(méi)有PPL的task強(qiáng)大,PPL的task可以鏈?zhǔn)竭B續(xù)執(zhí)行還可以組合任務(wù),TBB的task則不行。

PPL任務(wù)的鏈?zhǔn)竭B續(xù)執(zhí)行then

 

復(fù)制代碼

int main()

{

    auto t = create_task([]() -> int

    { 

        return 0;

    });

 

    // Create a lambda that increments its input value.

    auto increment = [](int n) { return n + 1; };

 

    // Run a chain of continuations and print the result. 

    int result = t.then(increment).then(increment).then(increment).get();

    cout << result << endl;

}

/* Output:

    3

*/

復(fù)制代碼

PPL任務(wù)的組合

 

  1.when_all可以執(zhí)行一組任務(wù),所有任務(wù)完成之后將所有任務(wù)的結(jié)果返回到一個(gè)集合中。要求該組任務(wù)中的所有任務(wù)的返回值類(lèi)型都相同。

 

復(fù)制代碼

array<task<int>, 3> tasks =

{

    create_task([]() -> int { return 88; }),

    create_task([]() -> int { return 42; }),

    create_task([]() -> int { return 99; })

};

 

auto joinTask = when_all(begin(tasks), end(tasks)).then([](vector<int> results)

{

    cout << "The sum is " 

          << accumulate(begin(results), end(results), 0)

          << '.' << endl;

});

 

// Print a message from the joining thread.

cout << "Hello from the joining thread." << endl;

 

// Wait for the tasks to finish.

joinTask.wait();

復(fù)制代碼

2.when_any任務(wù)組中的某一個(gè)任務(wù)執(zhí)行完成之后,返回一個(gè)pair,鍵值對(duì)是結(jié)果和任務(wù)序號(hào)。

 

復(fù)制代碼

array<task<int>, 3> tasks = {

        create_task([]() -> int { return 88; }),

        create_task([]() -> int { return 42; }),

        create_task([]() -> int { return 99; })

    };

 

    // Select the first to finish.

    when_any(begin(tasks), end(tasks)).then([](pair<int, size_t> result)

    {

        cout << "First task to finish returns "

              << result.first

              << " and has index "

              << result.second<<endl;

    }).wait();

//output: First task to finish returns 42 and has index 1.

復(fù)制代碼

 

 

總結(jié):

  ppl和tbb兩個(gè)并行運(yùn)算庫(kù)功能相似,如果需要跨平臺(tái)則選擇tbb,  否則選擇ppl。ppl在任務(wù)調(diào)度上比tbb強(qiáng)大,tbb由于設(shè)計(jì)上的原因不能做到任務(wù)的連續(xù)執(zhí)行以及任務(wù)的組合,但是tbb有跨平臺(tái)的優(yōu)勢(shì)。


想要了解更多詳情歡迎來(lái)電咨詢(xún)18678812288
登陸網(wǎng)址:m.h6244.cn。
聯(lián)系人:王經(jīng)理。

平阳县| 玛曲县| 治多县| 绍兴市| 南康市| 温宿县| 麦盖提县| 泉州市| 桐梓县| 宿州市| 洛南县| 武邑县| 青河县| 綦江县| 梓潼县| 泸定县| 长武县| 阿鲁科尔沁旗| 望江县| 横山县| 越西县| 邯郸县| 绵阳市| 阜新| 兰西县| 凌云县| 普兰县| 上高县| 西盟| 兴化市| 凤阳县| 衡山县| 新乡县| 安化县| 义乌市| 根河市| 乾安县| 和硕县| 新和县| 康平县| 会同县|