簡體   English   中英

在tbb parallel_pipeline中調整粒度

[英]Adjusting granularity in tbb parallel_pipeline

管道任務如下:

  1. 順序讀取約100-200 Mb壓縮文件(10-15k)
  2. 並行解壓縮每個文件
  3. 並行反序列化每個解壓縮的文件
  4. 處理結果反序列化的對象並獲得基於所有對象的一些值(均值,中位數,分組等)

當我獲得解壓縮的文件內存緩沖區時,序列化的塊一個接一個地移動,因此我想以相同的方式將其傳遞到下一個過濾器,或者至少通過將序列化的塊打包成一定數量的組來調整此過程,然后通過。 但是(據我了解),tbb_pipeline使我將指針傳遞給具有所有序列化塊的緩沖區,因為每個過濾器都必須獲取指針並返回指針。

據我所知,使用並發隊列來累積序列化對象的包會殺死使用tbb_pipeline的麻煩。 此外,過濾器中operator()的常量不允許擁有我自己的中間“任務池”(但是,如果每個線程都具有自己的“任務”存儲本地副本並只是從中切出正確的片段,大)

主要問題:在這種情況下,有什么方法可以“調整”粒度? (即某個過濾器獲取指向所有序列化對象的指針,並傳遞到下一過濾器對象小包裝)

重新格式化(分割等)輸入文件幾乎是不可能的。

第二個問題:當我累積處理結果時,我並不真正在乎任何順序,我只需要匯總統計信息即可。 我可以使用並行過濾器代替serial_out_of_order並在某個地方累積每個線程的處理結果,然后將它們合並嗎?

但是(據我了解),tbb_pipeline使我將指針傳遞給具有所有序列化塊的緩沖區,因為每個過濾器都必須獲取指針並返回指針。

首先,我認為最好使用更現代,類型安全的管道形式: parallel_pipeline 它不要求您傳遞任何特定數據的任何特定指針。 您只需指定下一階段需要哪種類型的數據就可以對其進行處理。 因此,這與第一個過濾器如何划分要由以下過濾器處理的數據有關。

主要問題 :在這種情況下,有什么方法可以“調整”粒度? (即某個過濾器獲取指向所有序列化對象的指針,並傳遞到下一過濾器對象小包裝)

您可以安全地將一種並行算法嵌入另一種並行算法中,以便在某些階段更改粒度,例如,在頂層,第一個管道通過文件列表; 第二個管道在嵌套級別讀取文件的大塊; 最后,最里面的管道將大塊分解為一些第二階段的塊。 請參見下面的嵌套示例。

第二個問題 :我可以使用並行過濾器代替serial_out_of_order並在某個地方累積每個線程的處理結果,然后將它們合並嗎?

是的,如果不修改共享數據,則始終可以使用並行過濾器。 例如,您可以使用tbb::combinable來收集特定於線程的部分和,然后將它們組合。

但是,如果每個線程都有自己的本地存儲用於“任務”的副本,並從中正確切出片段,那就太好了

是的,他們有。 每個線程都有其自己的本地任務池。


嵌套parallel_pipelines的一般示例

parallel_pipeline( 2/*only two files at once*/,
    make_filter<void,std::string>(
        filter::serial,
        [&](flow_control& fc)-> std::string {
            if( !files.empty() ) {
                std::string filename = files.front();
                files.pop();
                return filename;
             } else {
                fc.stop();
                return "stop";
            }
        }    
    ) &
    make_filter<std::string,void>(
        filter::parallel,
        [](std::string s) {

            // a nested pipeline
            parallel_pipeline( 1024/*only two files at once*/,
                make_filter<void,char>(
                    filter::serial,
                    [&s](flow_control& fc)-> char {
                        if( !s.empty() ) {
                            char c = s.back();
                            s.pop_back();
                            return c;
                         } else {
                            fc.stop();
                            return 0;
                        }
                    }    
                ) &
                make_filter<char,void>(
                    filter::parallel,
                    [](char c) {
                        putc(c, stdout);
                    } 
                )
            );
        } 
    )
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM