【问题标题】:boost coroutine with multi core增强多核协程
【发布时间】:2016-06-24 19:49:54
【问题描述】:

我的 tcp 服务器基于这个boost coroutine server example

每秒有很多请求,服务器有两个核心但只使用一个,在任务管理器的性能选项卡中它永远不会超过 50% cpu,并且一个核心始终是空闲的:

如何让 boost::coroutine 与多核一起工作?

我刚刚想出了一个添加thread_pool的解决方案:

#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include "thread_pool.h"
#include <iostream>

using boost::asio::ip::tcp;

class session : public std::enable_shared_from_this<session>
{
public:
  explicit session(tcp::socket socket) { }

  void go()
  {
      std::cout << "dead loop" << std::endl;
      while(1) {} // causes 100% cpu usage, just for test
  }
};

int main()
{
  try
  {

    boost::asio::io_service io_service;

    thread_pool pool(1000); // maximum 1000 threads

    boost::asio::spawn(io_service,
        [&](boost::asio::yield_context yield)
        {
          tcp::acceptor acceptor(io_service,
            tcp::endpoint(tcp::v4(), 80));

          for (;;)
          {
            boost::system::error_code ec;
            tcp::socket socket(io_service);
            acceptor.async_accept(socket, yield[ec]);
            if (!ec) {
                pool.enqueue([&] { // add this to pool
                    std::make_shared<session>(std::move(socket))->go();
                });
            }
          }
        });

    io_service.run();
  }
  catch (std::exception& e)
  {}

  return 0;
}

现在代码似乎在 telnet 127.0.0.1 80 两次后以 100% cpu 运行。

但是多核协同程序的常用方式是什么?

【问题讨论】:

  • 你能贴一张你的任务管理器的图片吗?你确定它只使用一个核心吗?
  • @ali786,用图片更新帖子。协程是单线程的,所以我猜一个线程不能在多核上运行。
  • 是的,协程的真正理念是只有一个系统线程能够同时运行多个函数。如果您想同时运行您的函数(占用两个内核),您至少需要 2 个系统线程。

标签: c++ multicore boost-coroutine


【解决方案1】:

一个线程只在一个内核上运行,因此您必须使用单独的协程创建多个线程。 asio 已经包含了一些线程管理支持,所以你主要需要启动一些线程:

int main() {
  std::vector<std::thread> pool;
  try {
    boost::asio::io_service io_service;
    {
      for(auto threadCount = std::thread::hardware_concurrency();
          threadCount;--threadCount)
        pool.emplace_back([](auto io_s) {return io_s->run(); }, &io_service);
    }

    // Normal code
  } catch(std::exception &e) {}
  for(auto &thread : pool) 
    thread.join();
  return 0;
}

重要的是在每个线程上运行io_service.run()。然后.async_accept之后就可以调用了

io_service.post(&session::go, std::make_shared<session>(std::move(socket)))

在池中的某处运行会话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 2014-05-05
    • 2018-12-23
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多