2017-02-09 67 views
1

我试图通过使用std::thread加速for循环。循环遍历包含数百万项目的列表。我给每个迭代到不同的线程。C++线程不加入“终止调用没有活动异常”

4047后迭代停止运行并抛出terminate called without an active exception Aborted (core dumped)

我相信这个错误通常是由线程引起了不被正确连接(在本网站上的其他问题说明)。不过,我有一个函数可以在我的for循环结尾加入所有线程。由于没有达到连接函数,我怀疑真正的问题是创建的线程太多。这是我第一次进入lambda和多线程,我不确定如何限制for循环中一次创建的线程数。

我的代码如下:

std::mutex m; 
std::vector<std::thread> workers; 
for (ot.GoToBegin(), !ot.IsAtEnd(); ++ot) // ot is the iterator 
{ 
    workers.push_back(std::thread([test1, test2, ot, &points, &m, this]() 
    { 
     // conditions depending on the current ot are checked 
     if (test1 == true) return 0; // exit function 
     if (test2 == true) return 0; 
     // ...etc, lots of different checks are performed.. 

     // if conditions are passed save the current ot 
     m.lock(); 
     points.push_back(ot.GetIndex()); 
     m.unlock(); 
    })); 
} // end of iteration 
std::for_each(workers.begin(), workers.end(), [](std::thread &t) 
{ 
    t.join(); // join all threads 
}); 

任何帮助,将不胜感激

+1

可能重复的[C++终止调用没有活动异常](http://stackoverflow.com/questions/7381757/c-terminate-called-without-an-active-exception) –

+0

创建数百万个线程不会要漂亮 - 我会建议看看线程池。 –

+0

该问题的解决方案是具有一个连接所有线程的函数。如上所述,我已经包含一个连接函数来加入所有线程完成for循环 – jla

回答

0

既然你每次得到错误的同时迭代,原因是没有“加入”本身。最有可能的,每个进程的线程的系统上的数量由4096或类似数量的限制,请参见Maximum number of threads per process in Linux?

当您创建的线程数,4047或std ::线程所以构造函数抛出异常,你永远不会得到到“加入”声明。

我建议你保持一个不是std :: tread(s)而是std :: future(s)的向量。该代码可能看起来大致是这样的:

typedef std::future<int> Future; 
std::vector<Future> results; 
for (...) { 
    results.emplace_back(std::async(std::launch::async, 
    [...](){ /* roughly same code as in your thread function */ })); 
} 
for (Future& result : results) { 
    auto value = result.get(); //waits for the task to finish 
    // process your values ... 
} 

未来(S)依靠内部线程池,所以你不会用完的线程。这些期货将随着线程变得可用而异步执行。

+1

感谢您的建议。它听起来像是受到系统的限制。我像你说的那样实现了一个期货向量,但是在抛出系统错误“资源暂时不可用”之前,它也运行了4047次迭代。我设立了一个柜台,一次分配4000个区块的期货,等待它们完成,清除了向量并分配了另一个4000期货的区块。这工作但开销是巨大的 - 超过50倍时比不paralleslised时。回到绘图板我猜。 – jla

+0

干得好!很可能你需要一个真正的带有“线程池”的库,例如英特尔TBB。或者,您可以搜索并使用一些专门的线程池模块。这当然需要重新设计一些数据结构。例如,全局互斥体应该去。相反,每个线程应该携带它的局部向量点,直到它准备好像在TBB模板“parallel_reduce”中合并它们一样。 –