我有大量(>> 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数量是线程实际使用的数量(四舍五入到页面大小)。我错了吗? –