2

要素の追加と削除を同時に実行しながら、unordered_map のキーをダンプしたいと考えています。完全にダンプするのに 4 秒かかります。長すぎます。次のように、別のスレッドにダンプすることは可能ですか:

while (1) {
    pthread_mutex_lock( &mutex ); 
    if(iter!=map.end()){
        x=iter->first
        iter++;    
    }
    pthread_mutex_unlock( &mutex );

    do_this(x);  // this takes time to complete
}

メインスレッドにいる間:

pthread_mutex_lock( &mutex ); 
map.erase(iter);

イテレータは消去後に無効になるため、順序付けられていないマップの消去方法は問題になりますか。

並行してダンプする他の安全な方法はありますか?

4

3 に答える 3

3

unordered_map(および一般的な連想コンテナー) の場合、メンバーerase()関数は、削除された要素以外の要素へのイテレーターおよび参照を無効に しません。

ただし、ここでは、ループがその要素への反復子を保持している間に、要素を消去してその要素への反復子を無効にする場合があります。たとえば、ループで逆参照される次の反復子によって参照される要素を削除した場合。

したがって、削除する要素が、サイクルの次のループで処理するイテレータによって参照されないように注意する必要があります。while

pthread_mutex_lock( &mutex ); 
if (i != iter)
{
    map.erase(i);
}
else
{
    // Maybe store in a queue of elements to be removed after the loop is done
}

iterループで使用される反復子変数はどこにありますか。

于 2013-02-03T14:37:17.093 に答える
1

参照:最初から最後まで反復しているときにマップ要素で erase() を呼び出すとどうなりますか?

do_thisそれを呼び出すメソッドを呼び出す前にイテレータをインクリメントするのでerase、問題は発生しません。

ちょっと考えてみてください:現在のアルゴリズムでは、ミューテックスはまったく必要ないと思います。

于 2013-02-03T14:39:59.283 に答える
1

要素を反復するのではなくバケットを反復することで、必要な並列処理の一部 (すべてではありません。これにより、消去が 4 秒全体を待機する必要がないように操作をインターリーブすることができます) を得ることができます。バケット数が減らない限り、これは安全です。

すなわち

pthread_mutex_lock( &mutex ); 
size_t count = map.bucket_count();
pthread_mutex_unlock( &mutex );

for(size_t i = 0; i<count; ++i){
  pthread_mutex_lock( &mutex );
  for(auto it = map.begin(i); it != map.end(i); ++i)
    do_this(it->first);
  pthread_mutex_unlock( &mutex );
}

do_this をミューテックスから引き出したい場合は、他の構造体に値を蓄積する必要があります

別の提案は、このマップが他の場所でどのように使用されているかに応じて、要素を消去する代わりに既知の無効な値にスワップし、ダンプ/do_this を実行しているスレッドに、この値が表示されたときに実際の消去を実行させることです。 .

于 2013-02-03T14:46:08.173 に答える