线程池C ++实现问题 [英] threadpool c++ implementation questions

查看:45
本文介绍了线程池C ++实现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此处此处,我们可以看到类似的线程池实现.

here and here , we can see similar threadpool implementations.

我的问题是关于将任务添加到线程池的功能,分别是上述项目中的添加入队.

my question is about function to add the task to threadpool, these are add and enqueue in projects above respectively.

因为这些看起来非常相似,所以我在这里发布了一个(来自第二个项目)

because these look very similar I'm posting a piece of one here (from second project)

auto ThreadPool::enqueue(F&& f, Args&&... args) 
-> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared< std::packaged_task<return_type()> >(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);

    // don't allow enqueueing after stopping the pool
        if(stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");

        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}

容器任务声明为:

std::queue< std::function<void()> > tasks;

所以我的问题是:

  1. 为什么在附加的 task 变量周围声明了带有附加包装std :: function的任务?为什么任务队列未声明为的容器std :: packaged_task也是可调用对象吗?我想任务队列应包含通用"可调用对象没有参数,没有返回类型.所以去除绑定和额外的包装器std :: function实现的参数协助删除返回类型,是正确还是否?同样关于shared_ptr的使用-是否只是为了避免packaged_task是可移动类型但std :: function是可复制类型的冲突?
  2. 对所有线程使用一个共享任务队列是一种好习惯吗?我正在看Anthony Williams的"C ++并发性"建议避免这种情况,以防止高速缓存行争用.和他建议对两个队列使用更高级的技术-全局和thread_local用于工作者的线程.
  1. why tasks declared with additional wrapper std::function around task variable ? why a queue of the tasks is not declared as a container of std::packaged_task which is also a callable object? I suppose that queue of the tasks should contains "universal" callable objects without parameters and without return type. so the removing parameters achieved by the binding, and extra wrapper std::function assists to remove return type, is it correct or no? also about the using of shared_ptr - is it only to avoid a collision that packaged_task is movable type but std::function is a copyable ?
  2. is it a good practice to use one shared task queue for all threads ? I'm looking at Anthony Williams "C++ Concurrency in action" he recommends to avoid this to prevent cache line contention. and he recommends to use more advanced technique with two levels of queue - global and thread_local for worker's threads.

推荐答案

如果您仍在寻找答案(您通常自己回答):

In case you are still looking for an answer (you mostly answered it on your own):

  1. 与您想象的完全一样.
  2. 这不是不好的做法".这不仅导致性能下降,不仅是由于缓存行争用,而且还因为任务列表上的争用.

当前的HPC线程池实现大多使用窃取工作的调度程序:每个工作程序都有自己的队列.工人将工作从自己的队列中拉出/推入,直到完成自己队列中的所有任务.然后,它会从其他工作人员那里窃取任务并执行这些任务.

Current HPC thread pool implementations mostly use a work stealing scheduler: Each worker has its own queue. The worker pulls and pushes work from/to his own queue, until he has finished all the tasks in its own queue. Then it steals tasks from other workers and executes those.

这篇关于线程池C ++实现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆