簡體   English   中英

使用多個線程的asio :: io_service優先級隊列處理

[英]asio::io_service priority queue handling with multiple threads

我在多線程C ++代碼中經常使用asio :: io_service。 最近,由於在處理各種任務時沒有優先級,我在代碼中發現了一個瓶頸。 我自然會遇到這個提升示例,以確保某些任務的優先級高於休息。 但是此示例僅在單線程應用程序中有效。

通常,我的代碼使用此模式。

boost::asio::io_service ioService;
boost::thread_group threadPool;
boost::asio::io_service::work work(ioService);

int noOfCores = boost::thread::hardware_concurrency();
for (int i = 0 ; i < noOfCores ; i ++)
{
    threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
threadPool.join_all();

我從其他各種線程中處理了很多ioService.post(),所有這些處理程序都具有相同的優先級。

現在,如果我要使用boost示例中的handler_priority_queue ,首先必須為add()和execute_all()函數添加一些互斥保護。

boost::mutex _mtx;
void add(int priority, boost::function<void()> function)
{
    boost::lock_guard<boost::mutex> lock(_mtx);
    handlers_.push(queued_handler(priority, function));
}

void execute_all()
{
    while (!handlers_.empty())
    {
        boost::unique_lock<boost::mutex> lock(_mtx);
        queued_handler handler = handlers_.top();
        handlers_.pop();
        lock.unlock();
        handler.execute();
    }
}

但是,我不確定用什么替換當前代碼中的以下行。

    threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));

我顯然需要以某種方式用handler_priority_queue :: execute_all()替換io_service :: run。 但是如何? 什么是最好的方法?

我可以做...

    threadPool.create_thread(boost::bind(&handler_priority_queue::execute_all,
&pri_queue));

但是execute_all()立即出現。 我認為execute_all()需要一些重新設計。 這個怎么樣? 它可以工作,但是我不確定陷阱。

void execute_all()
{
    while (ioService.run_one())
    {
        while (ioService.poll_one());
        while (true)
        {
            queued_handler handler;
            {
                boost::lock_guard<boost::mutex> lock(_mtx);
                if (handlers_.empty())
                {
                    break;
                }
                else
                {
                    handler = handlers_.top();
                    handlers_.pop();
                }
            }
            handler.execute();
        }
    }
}

Asio不提供這種可能性。 該示例僅限於單個線程,因為它不會修改Asio的調度程序。 調度程序以FIFO方式在線程之間分配任務,我不知道有任何修改方法。 只要在初始化異步操作(例如io_service::post )時無法指定優先級,調度程序就不會知道任務優先級,因此無法使用它。

當然,您可以在每個線程中使用priority_queue ,但是在這種情況下,您的優先級將產生有限的“線程本地”效果:僅將調度到同一線程的任務根據其優先級執行。 考慮示例(偽代碼):

io_service.post(task(priority_1));
io_service.post(task(priority_2));
io_service.post(task(priority_3));

thread_1(io_service.run());
thread_2(io_service.run());

假設任務1和3由thread_1 ,任務2由thread_2 因此,如果如鏈接示例中那樣使用優先級隊列,則thread_1將執行任務3,然后執行任務1。 但是thread_2這些任務,將立即執行任務2,可能在任務3之前執行。

您可以選擇實現自己的調度程序(復雜程度取決於您的要求,但總的來說可能很棘手)或找到第三方解決方案。 例如,我要檢查“英特爾TBB 優先級”

編輯:試圖闡述“自己的調度程序”的情況:

您需要一個非常好的多個生產者/多個消費者並發隊列,以獲得更簡單的版本,線程池和從隊列中拉出的線程。 從優先級的角度來看,這將是一個相當公平的解決方案:所有較高優先級的任務(幾乎總是)將在較低優先級的任務之前開始執行。 如果性能比公平更重要,則可以改進此解決方案。 但這將值得提出另一個問題,以及有關您的特定案例的許多細節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM