2017-11-09 3 views
0

私はバリアクラスの実装を試みました。私は分裂と征服のアルゴリズムを使用してこれをテストしたい。私のクラスは以下のように定義されます。分割するようdivideとconquer(バリアントがビジー状態で破壊されている)のバリヤークラスC++

class barrier{ 
private: 
    mutex mtx; 
    condition_variable cv; 
    atomic<int> counter; 
    atomic<int> waiting; 
    atomic<int> thread_count; 

public: 
    barrier(int count) : thread_count(count), counter(0), waiting(0) {} 

    void wait() 
    { 
     //fence mechanism 
     unique_lock<mutex> lock(mtx); 
     ++counter; 
     ++waiting; 
     cv.wait(lock, [&] {return counter >= thread_count; }); 
     --waiting; 
     if (waiting == 0) counter = 0; 
     for (int i = 0; i < thread_count; ++i) cv.notify_one(); 
     lock.unlock(); 
    } 
}; 

とアルゴリズムを征服次のように、私はそれを実装しました:

int main() { 
    vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 
    int n = size(v)/2; 

    while (n >= 1) { 
     dnc_light(v, n); 
     n /= 2; 
    } 

    return 0; 
} 

void dnc_light (vector<int> &v, int n) { 
    thread trd[50]; 
    barrier bar(n); 

    for (int i = 0; i < n; ++i) { 
     trd[i] = thread([&] { 
      v[i] += v[i + n]; 
      bar.wait(); 
     }); 
    } 
} 

「忙しいながら、破壊されたミューテックス」このしかし結果 - エラー。どうして?私はbarrier bar(...)のサイズを動的に処理する必要があります。

答えて

2

これにより、「ミューテックスがビジー状態で破壊されました」というエラーが発生します。どうして?

dnc_lightローカルbarrierオブジェクトを参照して複数のスレッドを作成します。次に、これらのスレッドがまだ使用しているローカルの「barrier」が破棄され、「ビジー中にmutexが破壊されました」というエラーが発生します。

また、スレッドはジョイン可能であるため、デストラクタはジョインもデタッチもされていないため例外がスローされます。

修正は関数から戻る前に、スレッドに参加するために、次のようになります。これは、ループ待機に参加するため、すべてのスレッドがとにかく終了するまで、あなたはまったく障壁を必要としない上記のコードで

void dnc_light(vector<int> &v, int n) { 
    vector<thread> trd(n); 
    barrier bar(n); 

    for (int i = 0; i < n; ++i) { 
     trd[i] = thread([&](){ 
      v[i] += v[i + n]; 
      bar.wait(); 
     }); 
    } 

    for(auto& t : trd) 
     t.join(); 
} 


barrier内の変数は、それが唯一のmutexを保持しながら、それらにアクセスするため、アトミックである必要はありません。簡略化:

class barrier { 
    mutex mtx; 
    condition_variable cv; 
    int const thread_count; 
    int counter{0}; 
    int waiting{0}; 

public: 
    barrier(int count) : thread_count(count) {} 

    void wait() { 
     unique_lock<mutex> lock(mtx); 
     ++counter; 
     ++waiting; 
     cv.wait(lock, [&](){ 
      return counter >= thread_count; 
     }); 
     if(waiting == thread_count) 
      cv.notify_all(); 
     if(!--waiting) 
      counter = 0; 
    } 
}; 
+0

私はちょうどそれをテストし、あなたの提案が動作します。私は2つの質問があります:それらを結合するのではなく、 'dnc_light'のスレッドをデタッチできますか?昨日、主な機能のすべてをコーディングしようとしましたが、同じエラーが発生しました。なぜなら、for-loopの後にバリアが破棄されたからです。 – SAFD

+0

@SAFDスレッドに参加する必要がないようにスレッドを切り離すことができます。ただし、その場合は、障壁が生きていることを確認する必要があります。これを行うための1つの方法は、 'auto barrier = make_shared (n);'であり、 'barrier'スマートポインタを値に渡してスレッドに渡すので、使用中は生きています。 –

+0

さて、それは私にとってはあまりにも複雑です、私は恐れています。 私が気づいたいくつかのさらなるテストの後で、合計は必ずしも136ではないことがあります。スレッドが計算を混乱させることがあります。 したがって、私は 'dnc_light'を変更しました:' v'' byvalを捕まえ、 '' temp''を持って合計を保存します。これにより、いくつかの問題が解決されました。私が今得する唯一のエラーは、いくつかのランダムな合計が「0」になるということです。 – SAFD

関連する問題