亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C ++ OpenMP Parallel For Loop - 替代std :: vector

C ++ OpenMP Parallel For Loop - 替代std :: vector

C++
小唯快跑啊 2019-08-28 09:21:26
C ++ OpenMP Parallel For Loop - 替代std :: vector 基于這個線程,OpenMP和STL向量,哪些數據結構是并行for循環中共享 std :: vector的好選擇?主要方面是速度,矢量可能需要在循環期間調整大小。
查看完整描述

2 回答

?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

您鏈接的問題是在“多個線程寫入單個容器的情況下,STL向量容器不是線程安全的”這一事實。如果您調用可能導致重新分配std::vector持有的基礎數組的方法,那么這只是正確的說法。push_back()pop_back()并且insert()是這些危險方法的例子。

如果您需要線程安全重新分配,那么庫intel線程構建塊為您提供并發向量容器。您不應該在單線程程序中使用tbb :: concurrent_vector,因為訪問隨機元素所花費的時間高于std :: vector執行相同操作所需的時間(即O(1))。然而,并發矢量電話push_back(),pop_back(),insert()在一個線程安全的方式,甚至當再分配發生。

編輯1:以下英特爾演示文稿的幻燈片46和47 給出了使用tbb :: concurrent_vector并發重新分配的說明性示例

編輯2:順便說一句,如果你開始使用英特爾Tread Building Block(它是開源的,它適用于大多數編譯器,它與C ++ / C ++ 11功能集成得比openmp好得多),那么你不需要使用openmp創建parallel_for,這是使用tbb的parallel_for的一個很好的例子。


查看完整回答
反對 回復 2019-08-28
?
HUWWW

TA貢獻1874條經驗 獲得超12個贊

我認為你可以std::vector在大多數時間使用OpenMP并且仍然具有良好的性能。例如,以下代碼std::vectors并行填充,然后將它們組合在一起。只要您的主循環/填充功能是瓶頸,這通??梢院芎玫毓ぷ鞑⑶沂蔷€程安全的。

std::vector<int> vec;#pragma omp parallel{
    std::vector<int> vec_private;
    #pragma omp for nowait //fill vec_private in parallel
    for(int i=0; i<100; i++) {
        vec_private.push_back(i);
    }
    #pragma omp critical
    vec.insert(vec.end(), vec_private.begin(), vec_private.end());}

編輯:

OpenMP 4.0允許使用用戶定義的縮減#pragma omp declare reduction。上面的代碼可以簡化為

#pragma omp declare reduction (merge : std::vector<int> : omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end()))std::vector<int> vec;#pragma omp parallel for reduction(merge: vec)for(int i=0; i<100; i++) vec.push_back(i);

編輯:到目前為止我所顯示的內容并沒有按順序填充向量。如果訂單很重要,那么這可以這樣做

std::vector<int> vec;#pragma omp parallel{
    std::vector<int> vec_private;
    #pragma omp for nowait schedule(static)
    for(int i=0; i<N; i++) { 
        vec_private.push_back(i);
    }
    #pragma omp for schedule(static) ordered    for(int i=0; i<omp_get_num_threads(); i++) {
        #pragma omp ordered
        vec.insert(vec.end(), vec_private.begin(), vec_private.end());
    }}

這樣可以避免為每個線程保存std :: vector,然后將它們串行合并到并行區域之外。我在這里了解了這個“技巧” 。對于用戶定義的縮減,我不確定如何做到這一點(或者甚至可能)。。用戶定義的縮減不可能做到這一點。

我剛剛意識到關鍵部分是不必要的,我從這個問題中找到了parallel-cumulative-prefix-sums-in-openmp-communic-values-between-thread。此方法也可以使訂單正確

std::vector<int> vec;size_t *prefix;#pragma omp parallel{
    int ithread  = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    #pragma omp single    {
        prefix = new size_t[nthreads+1];
        prefix[0] = 0;
    }
    std::vector<int> vec_private;
    #pragma omp for schedule(static) nowait    for(int i=0; i<100; i++) {
        vec_private.push_back(i);
    }
    prefix[ithread+1] = vec_private.size();
    #pragma omp barrier    #pragma omp single 
    {
        for(int i=1; i<(nthreads+1); i++) prefix[i] += prefix[i-1];
        vec.resize(vec.size() + prefix[nthreads]);
    }
    std::copy(vec_private.begin(), vec_private.end(), vec.begin() + prefix[ithread]);}delete[] prefix;


查看完整回答
反對 回復 2019-08-28
  • 2 回答
  • 0 關注
  • 1422 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號