gpt4 book ai didi

c++ - 使用 std::async 比非异步方法慢来填充 vector

转载 作者:太空宇宙 更新时间:2023-11-04 14:59:28 25 4
gpt4 key购买 nike

我正在试验 std::async 来填充 vector 。它背后的想法是使用多线程来节省时间。但是,运行一些基准测试我发现我的非异步方法更快!

#include <algorithm>
#include <vector>
#include <future>

std::vector<int> Generate(int i)
{
std::vector<int> v;
for (int j = i; j < i + 10; ++j)
{
v.push_back(j);
}
return v;
}

异步:

std::vector<std::future<std::vector<int>>> futures;
for (int i = 0; i < 200; i+=10)
{
futures.push_back(std::async(
[](int i) { return Generate(i); }, i));
}

std::vector<int> res;
for (auto &&f : futures)
{
auto vec = f.get();
res.insert(std::end(res), std::begin(vec), std::end(vec));
}

非异步:

std::vector<int> res;
for (int i = 0; i < 200; i+=10)
{
auto vec = Generate(i);
res.insert(std::end(res), std::begin(vec), std::end(vec));
}

我的 benchmark test显示异步方法比非异步方法慢 71 倍。我做错了什么?

最佳答案

std::async 有两种操作模式:

  1. std::launch::async
  2. std::launch::deferred

在这种情况下,您调用了 std::async 而未指定任何一个,这意味着它可以选择其中一个。 std::launch::deferred 基本上意味着在调用线程上完成工作。所以 std::async 返回一个 future,而对于 std::launch::deferred,您请求的操作将不会一直执行到您在那个future 上调用.get 为止。在某些情况下它可能有点方便,但它可能不是您在这里想要的。

即使您指定了 std::launch::async,您也需要意识到这会启动一个新的执行线程来执行您请求的操作。然后,它必须创建一个 future,并使用某种从线程到 future 的信号,让您知道您请求的计算何时完成。

所有这些都会增加相当多的开销——从微秒到毫秒左右,具体取决于操作系统、CPU 等。

因此,要使异步执行有意义,您异步执行的“事情”通常至少需要花费数十毫秒(数百毫秒可能是更合理的下限阈值)。我不会太纠结于确切的截止日期,但这需要花费一些时间。

因此,只有当数组比您在这里处理的要大得多时,异步填充数组才有意义。

但是对于填充内存,您很快就会遇到另一个问题:大多数 CPU 比主内存快得多,如果您所做的只是写入内存,那么单个线程很有可能已经饱和了内存路径,因此即使充其量异步完成这项工作也只会获得一点点 yield ,并且仍然很容易导致速度变慢。

异步操作的理想情况是,一个线程严重受内存限制,而另一个线程(例如)读取少量数据,并对少量数据进行大量计算。在这种情况下,计算线程将主要对缓存中的数据进行操作,因此它不会妨碍内存线程执行其操作。

关于c++ - 使用 std::async 比非异步方法慢来填充 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57682423/

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