2017-02-03 14 views
0

Недавно я создал программу поиска шаблонов в Game of Life от Conway, но она работала слишком медленно, чтобы быть практичной.
Итак, я решил распараллелить его, но я потерпел неудачу; это вызвало ошибку сегментации, что весьма вероятно из-за гонки данных.
Краткое описание кода:Что вызывает гонку данных в 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

Иногда сегментация ошибка возникает, когда '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]{ 
     /* ... */ 
    })); 

И все в порядке в настоящее время.

 Смежные вопросы

  • Нет связанных вопросов^_^