2014-12-06 2 views
3

Я хочу разбить вектор на маленькие векторы, обрабатывать каждый из них отдельно по потоку, а затем объединить их. Я хочу использовать std::async для создания потоков и мой код выглядит как этотstd :: async - аргумент вектор поврежден

void func(std::vector<int>& vec) 
{ 
    //do some stuff 
} 

// Calling part 
std::vector<std::future<void>> futures; 
std::vector<std::vector<int>> temps; 
for (int i = 1; i <= threadCount; ++i) 
{ 
    auto& curBegin = m_vec.begin() + (i - 1) * size/threadCount; 
    auto& curEnd = m_vec.begin() + i * size/threadCount; 
    std::vector<int> tmp(curBegin, curEnd); 
    temps.push_back(std::move(tmp)); 

    futures.push_back(std::async(std::launch::async, &func, std::ref(temps.back()))); 
} 
for (auto& f : futures) 
{ 
    f.wait(); 
} 

std::vector<int> finalVector; 
for (int i = 0; i < temps.size() - 1; ++i) 
{ 
    std::merge(temps[i].begin(), temps[i].end(), temps[i + 1].begin(), temps[i + 1].end(), std::back_inserter(finalVector)); 
} 

Здесь m_vec главного вектор, который раскалывается на мелкие векторы. Проблема в том, что когда я передаю вектор в func(), в функции он становится недействительным, либо размер равен 0, либо с недопустимыми элементами. Но когда я пытаюсь вызвать функцию без std::async, все работает нормально.

Так в чем проблема с std::async и есть ли что-нибудь особенное, что я должен был сделать?

Благодарим вас за внимание!

ответ

5

Если Перераспределение происходит в то время как вы итеративно расширения temps вектор, то очень вероятно, что std::ref(temps.back()) нить действует на это ссылки уже признаны недействительными область памяти. Вы можете избежать переездов путем резервирования памяти до последовательных push_back с:

temps.reserve(threadCount); 
+0

Большое спасибо! – nabroyan

3

Петр С. уже дал правильный ответ с решением, я просто добавить некоторые пояснения.

Итак, в чем проблема с std :: async и есть ли что-нибудь особенное, что я должен делать?

Проблема не в async.

Вы получите точно такой же эффект, если вы сделали:

std::vector<std::function<void()>> futures; 
// ... 
for (int i = 1; i <= threadCount; ++i) 
{ 
    // ... 
    futures.push_back(std::bind(&func, std::ref(temps.back()))); 
} 
for (auto f : futures) 
    f(); 

В этой версии я не использую async, создать несколько функциональных объектов затем запустить их все один за другим. Вы увидите ту же проблему с этим кодом, которая заключается в том, что объекты функции (или в вашем случае, задачи, выполняемые с помощью async) содержат ссылки на векторные элементы, которые уничтожаются при вставке в temps и вызывают его перераспределение.

Чтобы решить эту проблему, вам необходимо убедиться, что элементы в temps являются стабильными, то есть не разрушаются и не воссоздаются в другом месте, как показывает его ответ Петр С.

+0

Благодарим вас за подробные объяснения! – nabroyan

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