2017-02-03 12 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

'결과가 λ 식의 함수 범위에서 선언되어 수정되는 유일한 개체라는 것을 확신합니다. 모든 경우를 캡처하지 않고 결과 만 캡처하여 어떤 결과가 발생하는지 알 수 있습니다. – SingerOfTheFall

+0

간혹 세그먼트 화 lambda 스코프에서 선언되고'/ * All ... .../'로 수정되는'search_grid'가 코드에서 람다 범위의 패턴 유형으로 변환되는 동안 오류가 발생합니다. –

답변

0

나는 문제가 람다 캡처 관련이 있음을 발견 : 위의 SingerOfTheFall의 코멘트에 명시된 바와 같이

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

search_grid

는, 참조에 의해 캡처됩니다. 그리고 람다 범위 내에서 패턴 유형으로 변환됩니다. 문제는 search_grid으로 수정하고을 패턴 유형으로 변환하거나 그 반대로 수정할 수 있다는 것입니다. 데이터 경주!

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

을 그리고 모든 게 괜찮 지금 :

는 다음과 같이 방지 할 수 있고, 변환 람다 캡처 내에서 이루어진다.