std :: async将异步创建和执行的最大线程数是多少?

时间:2017-03-01 02:23:12

标签: c++ linux multithreading asynchronous g++

我有大量(>>> 100K)的任务,具有非常高的延迟(分钟)和非常少的资源消耗。可能它们都可以并行执行,我正在考虑使用std::async为每个任务生成一个未来。

我的问题是: std :: async将异步创建和执行的最大线程数是多少? (在Ubuntu 16-xx或CentOs 7.x上使用g ++ 6.x - x86_64)

对我来说,正确获取该数字非常重要,因为如果我没有足够的任务实际并行运行(等待),则延迟的累积成本会非常高。

为了得到答案,我首先检查了系统的功能:

bob@vb:~/programming/cxx/async$ ulimit -u
43735
bob@vb:~/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):

bob@vb:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 100000
COUNT: 100000: ids.size(): 32748
0:03.29

然后我在foo中取消注释睡眠线以增加2s的睡眠时间。结果时序与2到10K任务左右一致,但在某些时候,某些任务最终会共享相同的线程ID,并且每个额外任务的经过时间会增加2秒:

bob@vb:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10056
COUNT: 10056: ids.size(): 10056
0:02.24
bob@vb:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10057
COUNT: 10057: ids.size(): 10057
0:04.27
bob@vb:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10058
COUNT: 10058: ids.size(): 10057
0:06.28
bob@vb:~/programming/cxx/async$ ps -eT | wc -l
277

所以,看起来对于我的问题,在这个系统上,限制大约是10K。我检查了另一个系统,限制是4K的顺序。

我无法弄清楚:

  • 为什么这些价值如此之小
  • 如何根据系统规格预测这些值

1 个答案:

答案 0 :(得分:0)

使用linux上的g ++,直截了当的答案似乎是“在pthread_create失败并返回EAGAIN之前可以创建的最大线程数”。该数字可以受到几个不同值的限制,man pthread_create列出其中3个:

  • RLIMIT_NPROC:软资源限制(我的CentOs 7服务器上为4096,我的Ubuntu / VirtualBox笔记本上为43735)
  • /proc/sys/kernel/threads-max的值(分别为2061857和87470)
  • /proc/sys/kernel/pid_max(40960和32768 resp。)
  • 的值

systemd至少还有一个可能的限制,因为man logind.conf表示:

  

UserTasksMax =设置每个用户可以同时运行的最大OS任务数。它控制每用户切片单元的TasksMax =设置,有关详细信息,请参阅systemd.resource-control(5)。默认为33%,与内核在主机上的默认值相等,为10813,但在OS容器中可能更小。