提升,在io_service.post之前创建线程池

时间:2015-12-17 15:00:46

标签: c++ multithreading boost threadpool

我成功测试了一个关于boost io_service的例子:

for(x = 0; x < loops; x++)
{
    // Add work to ioService.
    for (i = 0; i < number_of_threads; i++)
    {   
        ioService.post(boost::bind(worker_task, data, pre_data[i]));
    }

    // Now that the ioService has work, use a pool of threads to service it.
    for (i = 0; i < number_of_threads; i++)
    {   
        threadpool.create_thread(boost::bind(
            &boost::asio::io_service::run, &ioService));      
    }

    // threads in the threadpool will be completed and can be joined.
    threadpool.join_all();
}

这将循环几次并且需要一点点长,因为每次为每个循环创建线程。

有没有办法创建所有需要的线程。 然后在循环中发布每个线程的工作。 工作结束后,需要等到所有线程完成工作后才能完成工作!

这样的事情:

// start/create threads
for (i = 0; i < number_of_threads; i++)
{   
    threadpool.create_thread(boost::bind(
        &boost::asio::io_service::run, &ioService));      
}

for(x = 0; x < loops; x++)
{
    // Add work to ioService.
    for (i = 0; i < number_of_threads; i++)
    {   
        ioService.post(boost::bind(worker_task, data, pre_data[i]));
    }

    // threads in the threadpool will be completed and can be joined.
    threadpool.join_all();
}

2 个答案:

答案 0 :(得分:2)

这里的问题是你的工作线程会在创建后立即完成,因为没有工作要做。 io_service::run()将立即返回,因此,除非您在所有工作线程都有机会呼叫run()之前设法潜入其中一个后呼叫,否则它们将立即完成。

解决此问题的两种方法:

  • 使用barrier阻止工作人员立即致电run()。只有在作品发布后才能解锁。
  • 使用io_service::work对象阻止run返回。您可以在发布所有内容后销毁工作对象(并且必须在再次尝试join工作人员之前执行此操作)。

答案 1 :(得分:0)

循环不是真正有用的。

这是一个更好的解决方法。 我在回调中获取数据:

void worker_task(uint8_t * data, uint32_t len)
{
    uint32_t pos = 0;
    while(pos < len)
    {
        pos += process_data(data + pos);
    }
}

void callback_f(uint8_t *data, uint32_t len)
{

    //split data into parts
    uint32_t number_of_data_per_thread = len / number_of_threads;

    // Add work to ioService.
    uint32_t x = 0;
    for (i = 0; i < number_of_threads; i++)
    {   
         ioService.post(boost::bind(worker_task, data + x, number_of_data_per_thread));
         x += number_of_data_per_thread ;
    }

    // Now that the ioService has work, use a pool of threads to service it.
    for (i = 0; i < number_of_threads; i++)
    {   
        threadpool.create_thread(boost::bind(
            &boost::asio::io_service::run, &ioService));      
    }

    // threads in the threadpool will be completed and can be joined.
    threadpool.join_all();
}

因此,从主机应用程序(媒体流)调用此回调非常快。如果正在进行的len足够大,则线程池是有意义的。这是因为工作时间高于线程的初始化时间并开始运行。

如果数据的len很小,则线程池的优势就会丢失,因为线程的初始化和启动需要花费更多的时间来处理数据。

现在问题是,是否可以让线程已经运行并等待数据。如果调用回调,则将数据推送到线程并等待完成。线程数是常量(CPU计数)。 因为它是来自主机应用程序的回调,所以指向数据的指针仅在回调函数中有效。这就是我必须等到所有线程都完成工作的原因。

即使在其他线程开始之前,线程也可以在获取数据后立即开始工作。没有同步问题,因为每个线程都有自己的数据存储区。