2017-02-09 41 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」中合併它們一樣。 –

相關問題