Std :: async - argument vector corrupted

I want to split a vector into small vectors, process each one separately on a stream, and then combine them. I want to use std::async

to create threads and my code looks something like this.

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));
}

      

Here m_vec

is the main vector, which is split into small vectors. The problem is that when I pass the vector in func()

, in the function, it becomes invalid, either the size is 0, or with invalid elements. But when I try to call the function without std::async

, everything works fine.

So what is the problem with std::async

and is there anything special that I should be doing?

Thank you for your time!

+3


source to share


2 answers


If reallocation occurs when you iteratively expand a vector temps

, then most likely the std::ref(temps.back())

thread in which the thread is running refers to an already invalid memory area. You can avoid relocations by allocating memory up to sequential push_back

s:



temps.reserve(threadCount);

      

+5


source


Peter S. already gave the correct answer with a solution, I'll just add some explanation.

So what's the problem with std :: async and is there anything special I should be doing?

The problem is not async

.

You would get the same effect if you did:



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();

      

In this version I am not using async

, I create multiple function objects and then run them one at a time. You will see the same problem with this code, which is that the function objects (or in your case the tasks being executed async

) contain references to vector elements that are destroyed when inserted into temps

and cause reallocation.

To solve the problem, you need to make sure that the elements are temps

stable, i.e. are not destroyed or recreated elsewhere, as his answer from Peter S.

+3


source







All Articles