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

Replacing many std::async calls by a threadpool

本文关键字:async 调用 std 许多 线程 替换      更新时间:2023-10-16

我有一个程序多次调用std::async。执行的任务时间很短(比如每个任务只需要几百毫秒)。我认为有显著的开销线程创建,我想知道我是否可以避免这种方式。列举作业的代码比作业的处理运行得快得多。因此我已经有了一种池化。它是这样的。我创建了一个'job slots'数组:

template <typename T>
struct job {
  std::future <void> fut;
  std::vector <T*> *result;
  bool inUse;
}

在并行代码开始之前,我初始化作业槽数组,只创建一次结果向量。然后,每次作业枚举代码枚举一个作业时,它都会查找一个未使用的作业槽。如果有空闲槽,它将启动(使用std::async)一个新作业,将future移到槽中。作业运行并填充结果向量。如果没有空闲槽位,则代码检查槽位中的任何期货是否准备就绪。如果是,则处理结果向量,然后使用该槽。如果没有,它会等待几毫秒。这段代码运行得非常好,并且可以精确地根据可用的处理器数量进行缩放。我了解到对std::async的每次调用都会创建一个新线程,实际上,我可以看到进程id在滚动。我想消除这个开销,在一开始就一次性地创建线程。如何继续?

我找到了这个线程池实现https://code.google.com/p/cppthreadpool/downloads/list但它指出,一个任务需要一到两秒钟才能有效。我不需要任何花哨的日程安排、优先级等等。我只是想消除重复构造和销毁线程的开销。

我运行了一个使用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();
    });