2014-12-06 83 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 2014-12-07 07:25:26

3

的Piotr S.已经给出一个可以解决的正确答案,我只是补充一些解释。

那么,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中的元素是稳定的,即不会在Piotr S的回答中显示的不同位置被破坏和重新创建。

+0

感谢您的详细解释! – nabroyan 2014-12-07 07:25:56