gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:41:16 26 4
gpt4 key购买 nike

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

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

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

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

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 中的 sleep 行以添加 2 秒的 sleep 时间。生成的时间与 2s 到 10K 左右的任务一致,但在超出此范围的某个时间点,一些任务最终共享相同的线程 ID,并且每个额外任务的运行时间增加 2s:

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 量级。

我想不通:

  • 为什么这些值这么小
  • 如何根据系统规范预测这些值

最佳答案

对于 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)

systemd 至少还有一个可能的限制,如 man logind.conf 所示:

UserTasksMax= Sets the maximum number of OS tasks each user may run concurrently. This controls the TasksMax= setting of the per-user slice unit, see systemd.resource-control(5) for details. Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller in OS containers.

关于c++ - std::async 将异步创建和执行的最大线程数是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42522065/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com