2017-02-03 10 views
0

私は最近ConwayのGame of Lifeでパターン検索プログラムを作成しましたが、実行が遅すぎて実用的ではありませんでした。
私はそれを並列化することにしましたが、失敗しました。それはセグメンテーション障害を引き起こし、これはデータ競争の可能性が非常に高い。
コードの簡単な説明は:std :: asyncのデータ競合の原因は何ですか?

/* ... */ 
#include <list> 
#include <mutex> 
#include <future> 
#include <iostream> 
#include <forward_list> 
int main() { 
    /* ... */ 
    while (true) { 
     /* ... */ 
     std::forward_list</*pattern type*/> results; 
     std::list<std::future<void>> results_future; 
     std::mutex results_mutex; 
     for (/*All the possible unique pattern in given grid*/) 
      results_future.push_back(std::async([&]{ 
       /*A very hard calculation*/ 
       if (/*The pattern is what I'm looking for*/) { 
        std::lock_guard<std::mutex> results_guard(results_mutex); 
        results.push_front(std::move(/*The pattern*/)); 
       } 
      })); 
     while (!results_future.empty()) { 
      results_future.front().wait(); 
      results_future.pop_front(); 
     } 
     if (!results.empty()) { 
      for (auto &res : results) 
       std::cout << "Pattern found:" << std::endl << res; 
      return 0; 
     } 
    } 
} 

私はresultsは、ラムダ式の関数スコープの外に宣言され、そこに変更されている唯一のオブジェクトであるかなり確信しているので、私はミューテックスとそれをロック。
しかし、データ競争はまだ存在します。それは何の原因ですか?

+0

デバッガで実行するとsegフォールトはどこに発生しますか?コールスタックとは何ですか? –

+0

'ラムダ式の関数スコープから宣言され、変更されている唯一のオブジェクトだと確信しています。すべてを捕捉せず、' results'をキャプチャして何が起こるかを確認してください。 – SingerOfTheFall

+0

時々、セグメンテーションラムダスコープから宣言され、 '/ * All the ... * /'で修正されている 'search_grid'がラムダスコープのパターン型に変換されている間、フォルトが発生します。 –

答えて

0

私は問題はラムダキャプチャに関連していることがわかった:

for (/*All the possible unique pattern in given grid*/) 
    results_future.push_back(std::async([&]{ 
     /*pattern type*/ patt_orig = search_grid; 
     /* ... */ 
    })); 

search_grid、上記SingerOfTheFallさんのコメントで述べたように、参照によって捕獲されます。そして、それはラムダスコープ内のパターンタイプに変換されます。問題は、search_gridに変更し、をパターンタイプに変換すること、またはその逆にすることができます。データ競争!

これは、変換はラムダキャプチャ以内に行われ、このように防止することができます。

for (/*All the possible unique pattern in given grid*/) 
    results_future.push_back(std::async([&, patt_orig = (/*pattern type*/)search_grid]{ 
     /* ... */ 
    })); 

そして、すべてが今、大丈夫です。

関連する問題