【问题标题】:Vector of futures for breaking up tasks?分解任务的期货向量?
【发布时间】:2015-04-11 07:49:09
【问题描述】:

我有来自 Web 服务的响应,如果数据项的数量很大,我想将其拆分为更小的请求,并并行执行请求和随后对该请求的解析。本质上,当第一个请求解析数据时,后续请求应该会获取它。

似乎有很多方法可以做到这一点,我想知道期货是否适合这种情况。我听到一些 cmets 不应该将期货用于 IO,而论点则相反。

实际上,我正在尝试这样做:

void Service::GetData(const Defn &defn) {
    // Split up the request into chunks if the  list is large
    size_t chunk_size = CONFIG.GetInt("Limits","BatchSize");
    if(chunk_size == 0) {
        auto response = GetResponse(defn);
        Parse(defn, *response);
    } else {
        std::vector<std::future<std::unique_ptr<Response>>> futures;
        for(int batch_num = 0; batch_num < (std::ceil(cardinality / chunk_size)); batch_num++) {
            futures.emplace_back(std::async(std::launch::async, &Service::GetResponse, defn, chunk_size, batch_num * chunk_size));
        }
        for(auto&& future : futures ) {
            Parse(defn, *future.get());
        }
    }
}

std::unique_ptr<Response> Service::GetResponse(const Defn &defn, size_t top, size_t skip) {
    // Do request and return response
}

但是,我收到一个错误“错误 C2064:术语不计算为采用 3 个参数的函数”,我不知道为什么。期货是否不允许将它们放入诸如向量之类的容器中?

如果是这样,我应该以不同的方式处理这个问题,还是有不同的方法来获取期货列表? IE。我必须使用打包任务吗?

我认为,理想情况下,这应该与内核数量更接近,而不是随意将响应分成块,然后尝试为每个块创建一个线程。

【问题讨论】:

  • Service::GetResponse()是静态成员函数吗?
  • 没有。它只是一个普通的类函数。
  • 那你为什么不把std::async中的对象传进去呢? GetResponse 有 4 个参数 - thisdefntopskip
  • 卫生署!错过了。谢谢!在某种程度上,这是我的问题的一部分,但另一部分是关于期货的。这里应该使用期货吗?还是为IO创建一个线程池更合适。我无法直接回答何时不使用期货进行 IO。
  • 我已经写了答案>

标签: multithreading c++11 concurrent.futures


【解决方案1】:
futures.emplace_back(
    std::async(std::launch::async,
        &Service::GetResponse, pService, defn, chunk_size, batch_num * chunk_size)
//                             ^^^^^^^^
    );

由于 GetResponse 不是静态成员函数,您应该将对象作为参数。


我不知道你具体是做什么的,所以不能给你具体的建议>o

但是,如果您对future 的异步任务感兴趣,我会向您介绍boost.asio。它是一个异步 I/O 库(是的,AS同步I/O),可以轻松与std::futureboost::future 配合使用。 (见this my question

在您的代码中,我认为Parse() 也可以进入future

futures.emplace_back(
    std::async(std::launch::async,
        [&] { GetResponse(...); Parse(...); }
    )
);

如果Parse不需要在同一个线程中运行或者顺序运行,我觉得更好——你可以并行运行几个Parse和几个GetResponse

【讨论】:

  • 我已将此标记为答案(实际上是 pService 我只是使用了此),因为它解决了编译的基本问题。我不允许加入 boost,所以我试图确保期货的使用是有效的,并且不需要担心并发问题。
  • @user3072517 对了,你的web请求I/O并行处理可以更高效吗?我想单线程 I/O 和多线程解析就足够了 >o
  • 是的,单个请求确实是单线程的,但按批次大小细分,因此可以在请求其他批次的同时进行解析。批处理阈值足够高,解析时间几乎与请求时间匹配,因此我不必让它以真正的多线程方式工作。不过,这样可能会更好。感谢您的帮助!
猜你喜欢
  • 2023-02-12
  • 2018-11-12
  • 2020-02-16
  • 2016-01-14
  • 2012-11-29
  • 2017-03-26
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
相关资源
最近更新 更多