C++ 用线程池替换许多std::async调用

C++ 用线程池替换许多std::async调用,c++,multithreading,threadpool,C++,Multithreading,Threadpool,我有一个程序可以多次调用std::async。所执行的任务相当短(比如每个任务都有几百毫秒)。我认为创建线程会有很大的开销,我想知道我是否能以某种方式避免这种情况。枚举作业的代码比处理作业的速度快得多。因此,我已经有了一种共享机制。事情是这样的。我创建了一个“工作槽”数组: template <typename T> struct job { std::future <void> fut; std::vector <T*> *result; boo

我有一个程序可以多次调用
std::async
。所执行的任务相当短(比如每个任务都有几百毫秒)。我认为创建线程会有很大的开销,我想知道我是否能以某种方式避免这种情况。枚举作业的代码比处理作业的速度快得多。因此,我已经有了一种共享机制。事情是这样的。我创建了一个“工作槽”数组:

template <typename T>
struct job {
  std::future <void> fut;
  std::vector <T*> *result;
  bool inUse;
}
模板
结构作业{
标准:未来未来未来;
std::向量*结果;
布尔因努斯;
}
在并行代码开始之前,我初始化作业槽数组,只创建一次结果向量。然后,每次作业枚举代码枚举作业时,它都会查找未使用的作业槽。如果有空闲插槽,它将启动(使用std::async)一个新作业,将未来移动到该插槽。作业将运行并填充结果向量。如果没有空闲插槽,那么代码将检查插槽中的任何未来是否已准备就绪。如果是,它将处理结果向量,然后使用该插槽。如果没有,它将等待几毫秒。这段代码运行得非常好,并且可以精确地扩展到可用的处理器数量。我了解到,对std::async的每次调用都会创建一个新线程,事实上,我可以看到进程ID在其中滚动。我想消除这种开销,在一开始就一次性地创建线程。如何进行

我找到了这个线程池实现
但它指出,一项任务需要一到两秒钟的时间才能有效完成。我不需要任何花哨的调度、优先级等。我只想消除重复构造和销毁线程的开销。

我运行了一个测试程序,使用std::async创建任务,发现许多任务都是由同一个线程运行的!!事实上,我看到2个线程运行了25个异步任务。看起来标准库已经进行了一些线程池

    std::vector<std::future<void>> futures;
    for (int i = 0; i < 25; ++i)
    {
        auto fut = std::async([]
        {          
            std::cout << std::this_thread::get_id() <<std::endl;
        });
        futures.push_back(std::move(fut));
    }
    std::for_each(futures.begin(), futures.end(), [](std::future<void> & fut)
    {
        fut.wait();
    });
std::向量期货;
对于(int i=0;i<25;++i)
{
auto fut=std::异步([]
{          

我可以运行一个使用std::async创建任务的测试程序吗?我发现很多任务都是由同一个线程运行的!!事实上,我看到两个线程运行了20个异步任务。那么标准库执行线程池?这是在什么操作系统上?我最感兴趣的是Linux。你如何确定使用的是同一个线程,而不是同一个线程ID?windows;vs2010;正在等待()最后一次在futures上。您的标准future调用缺少启动策略。运行时实现可能会选择在主线程中运行它们。您可以尝试使用
std::launch::async
吗。我在linux上,获得了25个不同的线程ID。我使用
std::launch::async
为25个任务提供了大约6个线程。1:4线程:任务我相信你能做到say@MooingDuck当我尝试在windows中手动使用VS时,看起来任务正在线程池中执行。但是所有文档都说launch::async将创建一个新线程。您是否可以共享任何源来证明“MSVC使用线程池,重用线程”?“模板函数async异步运行函数f?”(可能在一个单独的线程中,该线程可能是线程池的一部分),并返回一个std::future,该std::future最终将保存该函数调用的结果