2017-11-29 2 views
0

std::setオブジェクトを設定し、C++で並列スレッドを使用してブール値ベクトルを編集できますか?並列スレッドを使用してセットにデータを書き込む際に危険がありますか?

私は並列計算に比較的新しく、OpenMPを使うことだけを学んでいます。読んでいる限り、スレッド間でデータ構造を共有してもいいと言う人がいると聞いてきました。

私の質問は、順序が重要でない限り、パラレルメソッドを使用していくつかのデータ構造を設定できますか?あるいは、あなたが一般的にそのようなことをしない理由は、単に注文が保存されないということだけです。ここで

は私がやろうとしていますものです:

input: std::vector<Object> u_set // vector containing universal set 

int NUM_ELEMENTS = 1000; 
std::set<int> my_set(); // set to be populated 
std::vector<bool> my_bools(u_set.size(), false); // vector containing set membership information (true/false) 
#pragma omp parallel for 
for (int i = 0; i < NUM_ELEMENTS; ++i){ 
    int next_el = get_next_element(); // next element from u_set 
    my_set.insert(next_el); 
    my_bools[next_el] = true; 
} 

コードは基本的にmemeberとして普遍集合から要素を選択し、サブセットにその値を追加し、ブールベクトルでそれをマークサブセット。これを並行して行うのは大丈夫ですか?それとも悪い形だと思われますか?このようなものが良いのでしょうか?

input: std::vector<Object> u_set // vector containing universal set 

int NUM_ELEMENTS = 1000; 
std::set<int> my_set(); // set to be populated 
std::vector<bool> my_bools(u_set.size(), false); // vector containing set membership information (true/false) 

int max_threads = omp_get_max_threads(); 
std::vector<std::vector<int> > elements(max_threads); // vector to contain data from each thread, so not accessing the same data structure 

#pragma omp parallel for 
for (int i = 0; i < NUM_ELEMENTS; ++i){ 
    int next_el = get_next_element(); // next element from u_set 
    int curr_thread = omp_get_thread_num(); 
    elements[curr_thread].push_back(next_el); 
} 

for (auto it = elements.begin(); it != elements.end(); ++it){ 
    for (auto jt = elements[*it].begin(); jt != elements[*it].end(); ++it){  
    my_set.insert(*jt); 
    my_bools[*jt] = true; 
    } 
} 

これは、スレッドごとに別々のベクターを行い、その後、終了時にそれらを結合します。私はそれが技術的には同じデータ構造にまだアクセスしていることを知っていますが、私の考えでは、全体のデータ構造全体でベクトルを分離することで、混乱することからセキュリティレベルが向上します。

これを行うより良い方法ですか?または同じセットにアクセスしてアルゴリズムが進むにつれてそれに追加するのはいいですか?

+4

短い答えは:いいえ。 'std :: set'はスレッドセーフではありません。 –

+0

'const'メンバ関数だけが同時にアクセスできます。 http://en.cppreference.com/w/cpp/container#Thread_safetyを参照してください。 –

+0

十分ですが、このコードを並列化するために提案できるものはありますか?第二の方法は安全でしょうか?同じベクトルでpush_backを呼び出さないためですか? – guskenny83

答えて

1

stdコンテナのほとんどの非constメソッドを呼び出すことはできませんが、他のスレッドは他のメソッドを呼び出します。 (begin()およびend()とその他の例外は例外です)。

だからいいえ。

他の並列ライブラリで使用される手法の1つは、各スレッドがサブコンテナに変更を蓄積し、バイナリツリーのようにワーカースレッドによって自動的に最終結果にマージされることです。これはあなたが使用しているツールではあまり合理的ではありません。

+0

2番目の方法でも機能しませんか?スレッドごとに別々のベクトルを保持していますか? – guskenny83

関連する問題