青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數據加載中……

Intel TBB::Pipeline,按序處理數據

在上一篇文章(TBB:pipeline,軟件流水線的威力)最后提出了幾個問題,我們逐個來看看TBB::Pipeline是怎么解決的。

 

 

為什么Pipeline可以保證數據執行的順序?既然TBB歸根到底是通過多線程執行任務,為什么不會在讀入先后兩個字符串后,后讀入的字符串先被下一個task處理?Pipeline里是不是有一個類似于FIFO 先進先出隊列之類的東西?

 

 

之前曾經質疑過Pipeline的性能,甚至想自己用MultiThreading來模擬一個流水線,但很快就發現其中實現的難點。數據執行的順序性就是其中之一。

 

假設以一個thread代表流水線上的一個節點,如果某節點是并發執行的,那么就需要2個以上的thread(AB),上一節點處理完畢的順序數據到底是先送給A還是B呢?處理完畢后后又該先將A還是B中的數據送到下一節點呢?即使可以人為的指定AB之間的優先規則,由于thread本身被調度的不確定性,實際運行中還是有很多不可預知的困難。

 

流水線的一個顯著特性就是保證每個數據均以相同的順序流過每個節點。因此,TBB::Pipeline中的一個首要任務就是在節點被并發執行的同時,仍能夠保證所處理的數據的次序而不需額外的處理代碼。此外,在要求串行處理的節點,要保證即使排在前面的數據先被處理,即使排在后面的數據先到達。

 

Pipeline的中心思想就是以token來控制數據的處理順序和流水線的深度。Pipeline::run函數中指定了token的最大值:

 

void pipeline::run( size_t max_number_of_live_tokens ) {}

 

 

每一個數據在進入Pipeline的時候都會按照先后順序依次分配一個token,如line1處:

 

task* stage_task::execute() {

    __TBB_ASSERT( !my_at_start || !my_object, NULL );

    if( my_at_start ) {

        if( my_filter->is_serial() ) {

            if( (my_object = (*my_filter)(my_object)) ) {

                my_token = my_pipeline.token_counter++; //line1

                my_token_ready = true;

                ITT_NOTIFY( sync_releasing, &my_pipeline.input_tokens );

                if( --my_pipeline.input_tokens>0 )

                    spawn( *new( allocate_additional_child_of(*my_pipeline.end_counter) ) stage_task( my_pipeline ) );

            } else {

                my_pipeline.end_of_input = true; //line2

                return NULL;

            }

...

}

 

如果當前流水線中的token全部用完了,那么暫時就不會處理新的數據,直到已進入Pipeline的數據被處理完畢有空閑的token(line2)

 

仍然以TBB中的例子text_filter為例考慮,流水線為 MyInputFilter->MyTransformFilter->MyOutputFilerMyInputFilter從磁盤上讀取數據,MyTransformFilter轉換成大寫字母,MyOutputFilter將轉換好的數據寫入磁盤。因此,MyInputFilter節點和MyOutputFiler節點必須是串行執行,而MyTransformFilter可以并發執行。對于MyInputFilter讀入的一串順序數據,token依次為1->2->3,如何保證經過轉換后數據也是以相同的順序寫入磁盤?

 

秘密在于TBB中的一個類tbb::internal::ordered_bufferMyOutputFilter用它來保證按照token的順序執行其隊列中的數據,而不管數據進入隊列的先后次序,換句話說,即使排在后面的數據token 2先被某個MyTransformFilter節點處理完畢送往MyOutputFilter,只要數據token 1沒到達沒被MyOutputFilter執行,數據2就不會在數據1之前先寫入磁盤。每一個需要被串行處理的節點,都會有一個ordered_buffer類型的成員變量。

 

先看看ordered_buffer的定義:

 

//! A buffer of ordered items.

/** Each item is a task, inserted into a position in the buffer corrsponding to a Token. */

class ordered_buffer {

    typedef  Token  size_type;

 

    //! Array of deferred tasks that cannot yet start executing.

    /** Element is NULL if unused. */

    task** array; //數組,以順序方式保存所有待處理的task

 

    //! Size of array

    /** Always 0 or a power of 2 */

    size_type array_size; //數組的尺寸

 

    //! Lowest token that can start executing.

    /** All prior Token have already been seen. */

    Token low_token; //當前正在處理的token,

 

    //! Serializes updates.

    spin_mutex array_mutex; //用于保護array并發訪問的鎖

};

 

仍然是在task* stage_task::execute() {

...

 if( ordered_buffer* input_buffer = my_filter->input_buffer ) {

            // The next filter must execute tokens in order.

            stage_task& clone = *new( allocate_continuation() ) stage_task( my_pipeline, my_filter );

            clone.my_token = my_token;                       //token

            clone.my_token_ready = my_token_ready;

            clone.my_object = my_object;                    //數據

            next = input_buffer->put_token(clone);//task放入隊列

        } else {

            /* A semi-hackish way to reexecute the same task object immediately without spawning.

               recycle_as_continuation marks the task for future execution,

               and then 'this' pointer is returned to bypass spawning. */

            recycle_as_continuation();

            next = this;

        }

    } else {

...

}

 

對于需要被串行處理的節點,使用ordered_bufferput_token函數將相關的數據和task引用放入隊列。put_token的實現是關鍵:

 

    template<typename StageTask>

    task* put_token( StageTask& putter ) {

        task* result = &putter;

        {

            spin_mutex::scoped_lock lock( array_mutex );

            Token token = putter.next_token_number();

            if( token!=low_token ) {

                // Trying to put token that is beyond low_token.

                // Need to wait until low_token catches up before dispatching.

                result = NULL;

                __TBB_ASSERT( (tokendiff_t)(token-low_token)>0, NULL );

                if( token-low_token>=array_size )

                    grow( token-low_token+1 );

                ITT_NOTIFY( sync_releasing, this );

                array[token&array_size-1] = &putter;

            }

        }

        return result;

    }

這個函數的實質是,首先取得下一個要處理的token,然后把待執行的task放到ordered_buffer的任務隊列中的"合適位置",而low_token指向當前需要處理的token編號。

 

例如low_token=0,當前需要處理0token,下一個token1,因此task保存在array[1]處并處于阻塞狀態,待0token處理完畢后,low_token增加1,再從array數組中取出1token對應的task進行處理。

 

Pipeline中是這樣通知串行節點以處理好一條數據的:

還是在task* stage_task::execute() {

...

if( ordered_buffer* input_buffer = my_filter->input_buffer )

            input_buffer->note_done(my_token,*this);

...

}

 

看看note_done的實現會有一種大徹大悟的感覺!如果剛完成的token就是次序最優先的token(low_token),那取出下一個要執行的task,以spawn的方式讓TBBtask scheduler來調度:

 

 

//! Note that processing of a token is finished.

    /** Fires up processing of the next token, if processing was deferred. */

    void note_done( Token token, task& spawner ) {

        task* wakee=NULL;

        {

            spin_mutex::scoped_lock lock( array_mutex );

            if( token==low_token ) {

                // Wake the next task

                task*& item = array[++low_token & array_size-1];

                ITT_NOTIFY( sync_acquired, this );

                wakee = item;

                item = NULL;

            }

        }

        if( wakee ) {

            spawner.spawn(*wakee);

        }

    }

 

 

 

 

ordered_buffer是一個非常有趣的實現,相比于常見的用FIFO queue來實現線程間的數據傳遞,ordered_buffer可謂精巧。我們可以好好利用ordered_buffer的原理來進一步改進我們的代碼。

 

posted on 2009-05-02 01:53 肥仔 閱讀(2536) 評論(0)  編輯 收藏 引用 所屬分類: 庫 & 代碼段

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲伦理久久| 欧美激情第3页| 久久久久国产精品www| 蜜臀av一级做a爰片久久| 在线视频精品一| 国产精品一区二区在线| 亚洲素人在线| 一区二区三区精品视频在线观看 | 久久高清免费观看| 国产精品免费小视频| 欧美专区在线观看| 蜜臀av性久久久久蜜臀aⅴ四虎| 亚洲国产成人在线视频| 性欧美长视频| av成人免费观看| 亚洲日本成人网| 国产麻豆成人精品| 亚洲精品一区二区三区婷婷月| 亚洲片在线观看| 香蕉av福利精品导航| 日韩一级二级三级| 久久av在线看| 久久精品日韩一区二区三区| 国产精品久久毛片a| 亚洲日本成人女熟在线观看| 亚洲区一区二区三区| 免费欧美在线| 欧美激情一区在线观看| 在线观看欧美成人| 亚洲主播在线| 国产欧美综合一区二区三区| 亚洲欧美色一区| 久久综合色婷婷| 一本色道久久加勒比精品| 国产精品成人久久久久| 性欧美办公室18xxxxhd| 亚洲激情在线| 欧美一区二区三区免费大片| 欧美一区成人| 亚洲精品美女在线观看播放| 亚洲自拍偷拍一区| 亚洲激情视频网| 国产精品美女久久久久久免费| 欧美一级二级三级蜜桃| 日韩网站在线| 91久久久久| 欧美黄网免费在线观看| 亚洲欧美另类综合偷拍| 精品av久久久久电影| 亚洲二区三区四区| 亚洲一区自拍| 国产日韩精品在线| 国产精品久久久久永久免费观看 | 国产精品99久久久久久久久久久久| 国产一区二区三区在线观看精品| 欧美激情精品久久久久久变态| 国产日韩成人精品| 国产精品私房写真福利视频| 欧美色道久久88综合亚洲精品| 欧美极品在线播放| 国产精品久久久久久五月尺 | 久久免费一区| 久久精品视频免费| 久久久久女教师免费一区| 久久激情五月婷婷| 欧美大片免费久久精品三p| 亚洲成人资源| 亚洲欧洲精品一区二区精品久久久 | 亚洲欧美另类久久久精品2019| 久久久99免费视频| 欧美黄网免费在线观看| 国产亚洲欧美中文| 亚洲欧美日韩精品久久奇米色影视| 91久久国产综合久久91精品网站| 国产一区在线播放| 亚洲手机视频| 一本久道久久综合中文字幕| 欧美美女福利视频| 麻豆精品在线视频| 狠狠网亚洲精品| 日韩一区二区福利| 午夜久久一区| 亚洲欧美日韩在线不卡| 在线看成人片| 亚洲永久网站| 亚洲人成网站影音先锋播放| 国产日韩欧美视频| 中文国产亚洲喷潮| 欧美成人国产一区二区| 久久久久久久久蜜桃| 国产精品国产三级国产普通话99| 99成人在线| 欧美激情中文不卡| 蜜臀av一级做a爰片久久| 亚洲大胆人体视频| 欧美电影专区| 欧美揉bbbbb揉bbbbb| 99视频精品免费观看| 亚洲毛片播放| 国产精品乱码妇女bbbb| 午夜精品福利电影| 新67194成人永久网站| 一区在线观看| 亚洲欧洲偷拍精品| 欧美日韩不卡一区| 久久综合伊人77777蜜臀| 麻豆亚洲精品| 亚洲五月婷婷| 久久一区国产| 久久综合给合久久狠狠色| 激情六月综合| 一本色道久久加勒比88综合| 国产视频久久| 日韩午夜在线视频| 一区二区欧美在线| 国产精品日韩欧美一区二区三区| 久久九九久久九九| 欧美全黄视频| 欧美成人一品| …久久精品99久久香蕉国产| 日韩亚洲一区在线播放| 好吊妞**欧美| 欧美一区二区三区另类| 亚洲美女在线国产| 久久综合婷婷| 久久久久久有精品国产| 国产色爱av资源综合区| 亚洲免费成人av电影| 亚洲人成网站在线观看播放| 久久国产欧美精品| 久久久人成影片一区二区三区观看 | 久热爱精品视频线路一| 欧美一级片久久久久久久| 久久久成人精品| 久久精品99无色码中文字幕| 国产精品视频男人的天堂| 日韩一级片网址| 欧美一区二区三区电影在线观看| 久久亚洲私人国产精品va媚药 | 亚洲激情电影在线| 国内精品视频在线观看| 亚洲欧美三级在线| 另类图片国产| 亚洲人成亚洲人成在线观看图片| 欧美福利网址| 一区二区三区国产在线| 最新日韩在线视频| 亚洲国产精品久久精品怡红院| 国产精品wwwwww| 国产一区二区按摩在线观看| 亚洲天堂av电影| 99re6热在线精品视频播放速度| 久久久久.com| 一区在线观看视频| 免费久久精品视频| 蜜臀av性久久久久蜜臀aⅴ| 亚洲精品一区二区三区婷婷月 | 久久综合图片| 亚洲国产精品一区二区www在线| 欧美激情小视频| 欧美日韩网址| 久久精品日韩一区二区三区| 久久久91精品国产| 在线观看视频一区二区| 亚洲二区在线观看| 欧美日韩另类综合| 先锋资源久久| 久久久亚洲成人| 亚洲精品免费看| 在线亚洲欧美专区二区| 国产亚洲精品久久久久久| 欧美a级一区二区| 欧美日韩精品综合在线| 久久激情婷婷| 欧美搞黄网站| 久久av一区| 欧美成人r级一区二区三区| 亚洲视频在线视频| 久久五月激情| 久久综合999| 亚洲一区二区动漫| 欧美国产一区二区在线观看| 欧美精品免费在线| 亚洲人精品午夜| 亚洲欧洲av一区二区| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲最快最全在线视频| 激情久久久久| 亚洲一区www| 亚洲日韩视频| 欧美一区不卡| 亚洲男人的天堂在线观看| 狼狼综合久久久久综合网 | 99国产精品私拍| 亚洲伦伦在线| 影音先锋另类| 久久精品国语| 性欧美xxxx大乳国产app| 亚洲美女精品成人在线视频| 国产日韩欧美一区二区三区在线观看|