我有大量(>> 100K)的任務,具有非常高的延遲(分鐘)和非常少的資源消耗。可能他們都可以並行執行,我正在考慮使用std::async
爲每個任務生成一個未來。std :: async將異步創建和執行的最大線程數是多少?
我的問題是:什麼是std :: async將異步創建和執行的線程的最大數量是多少? (在Ubuntu 16-xx或CentOs 7.x-x86_64上使用g ++ 6.x)
對我來說很重要,因爲如果我沒有足夠的任務實際運行(等待)並行累積延遲成本將非常高。
要得到一個答案,我開始檢查系統的功能:
[email protected]:~/programming/cxx/async$ ulimit -u
43735
[email protected]:~/programming/cxx/async$ cat /proc/sys/kernel/threads-max
87470
根據這些數字,我期待能在運行(主要是等待)的43K線程爲了得到在平行下。爲了驗證這一點,我寫了下面的程序檢查不同的線程ID的數量,並呼籲100K std::async
一個空任務所需的時間:
#include <thread>
#include <future>
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <string>
std::thread::id foo()
{
using namespace std::chrono_literals;
//std::this_thread::sleep_for(2s);
return std::this_thread::get_id();
}
int main(int argc, char **argv)
{
if (2 != argc) exit(1);
const size_t COUNT = std::stoi(argv[1]);
std::vector<decltype(std::async(foo))> futures;
futures.reserve(COUNT);
while (futures.capacity() != futures.size())
{
futures.push_back(std::async(foo));
}
std::vector<std::thread::id> ids;
ids.reserve(futures.size());
for (auto &f: futures)
{
ids.push_back(f.get());
}
std::sort(ids.begin(), ids.end());
const auto end = std::unique(ids.begin(), ids.end());
ids.erase(end, ids.end());
std:: cerr << "COUNT: " << COUNT << ": ids.size(): " << ids.size() << std::endl;
}
的時間是罰款,但不同的線程ID的數量是多少低於預期(的32748,而不是43735):
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 100000
COUNT: 100000: ids.size(): 32748
0:03.29
然後我取消註釋中foo
睡眠線增加一個2秒的睡眠時間。得到的時序與2S高達10K任務或如此一致,但超出了一些點,一些任務最終上漲2秒,每增加任務共享相同的線程ID和經過時間的增加:
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10056
COUNT: 10056: ids.size(): 10056
0:02.24
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10057
COUNT: 10057: ids.size(): 10057
0:04.27
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10058
COUNT: 10058: ids.size(): 10057
0:06.28
[email protected]:~/programming/cxx/async$ ps -eT | wc -l
277
所以,看起來對於我的問題,在這個系統上,限制在10K左右。我檢查了另一個系統,限制在4K的數量級。
我想不通:
- 爲什麼這些值是如此之小
- 如何在Linux系統
那麼,每個線程都需要從操作系統獲取一些資源。線程堆棧的典型默認大小爲8MB,因此需要總共_thread-count * 8MB_的DRAM。這不僅是關於啓動更多的線程,你需要有資源...閱讀[這裏](http://stackoverflow.com/questions/25814365/when-to-use-stdasync-vs-stdthreads)了。 – Arash
沒有幾乎同樣荒謬的處理核心的荒謬數量的任務並不是那麼有用。這些線程將花費大部分時間來爭取訪問處理器。考慮使用線程池。 – user4581301
@arash感謝您的鏈接。關於DRAM的使用,即使默認的線程堆棧大小爲8MB,我也會認爲這是虛擬內存,並且實際需要的DRAM數量是線程實際使用的數量(四捨五入到頁面大小)。我錯了嗎? –