std :: thread не получит мой процессор более 20% нагрузки? - PullRequest
0 голосов
/ 16 октября 2018

Может быть, я использую std :: thread неправильно?У меня есть 12-процессорный процессор и встроенный движок рендеринга.Больше похоже на плоттер для таких вещей, как perlin noise и т. Д. Так как рендеринг был довольно медленным, я использовал std :: thread, чтобы полностью использовать мои 12 ядер.На самом деле скорость рендеринга резко возросла, но мое использование процессора не будет выше, чем при использовании одного потока ....

Это мой код, отвечающий за рендеринг ... позвольте мне объяснитьэто ...

void Renderer::Render(sf::Image * _img,
                      sf::Vector2f _dims,
                      unsigned _threadCount)
{
    im = _img;
    dims = _dims;

    im->create(dims.x, dims.y, sf::Color(100, 0, 0, 255));

    static float bar = 0.3f;
    float g = 0.01f;

    std::vector < std::thread > workers;

    for (unsigned i = 0; i < _threadCount; ++i)
    {
        workers.push_back(std::thread(Renderer::RenderThread,
                                      sf::IntRect((dims.x / _threadCount) * i,
                                                  0,
                                                  (dims.x / _threadCount) * (i + 1),
                                                  dims.y),
                                      bar,
                                      g,
                                      sf::Color(0,
                                                (255.0f / _threadCount) * i,
                                                0)));
    }

    bar += 0.01f;

    for (unsigned i = 0; i < workers.size(); ++i)
    {
        workers[i].join();
    }

    return;
}

void Renderer::RenderThread(sf::IntRect area, float bar, float g, sf::Color clr)
{
    for (unsigned x = area.left + 1; x < area.width + 1; x++)
    {
        for (unsigned y = area.top + 1; y < area.height + 1; y++)
        {
            im->setPixel(x - 1, y - 1, ImAlg::Tiles0(x, y, bar, 5));
        }
    }

    return;
}

Итак, в основном это следующее: верхняя функция - это основная функция, которая вызывается фреймворком.Это создает темы.Нижняя функция - это функция, которая выполняется в каждом потоке.Я попытался разделить изображение, которое будет отображаться на четные части.Например, если изображение имеет ширину 1000 и я использую 4 потока, каждый поток будет отображать 250x1000 px

1 Ответ

0 голосов
/ 16 октября 2018

Не используйте сырые темы.Начните с простого пула потоков:

struct thread_pool {
  std::future<void> run( std::function<void()> f ){
    std::packaged_task<void()> t(std::move(f));
    auto r = t.get_future();
    auto l = lock();
    q.push_back(std::move(t));
    cv.notify_one();
    return r;
  }
  void start(std::size_t n){
    //std::cout << n << " threads starting" << std::endl;
    while(n--)
      threads.push_back( std::thread([this]{loop();}) );
   }
  ~thread_pool(){
    end();
    for (auto&&t:threads)t.join();
  }
private:
  void end(){
    auto n=threads.size();
    auto l=lock();
    for(auto count=n;count;--count)
      q.emplace_back();
    cv.notify_all();
    //std::cout << n << " threads ended" << std::endl;
  }
  void loop(){
    while(true){
      //std::cout << "Waiting..." << std::endl;
      auto t=pop();
      //std::cout << "Got " << t.valid() << std::endl;
      if (!t.valid()) break;
      //std::cout << "Running..." << std::endl;
      t();
    }
  }
  std::packaged_task<void()> pop(){
    auto l=lock();
    cv.wait(l, [&]{ return !q.empty();});
    auto r = std::move(q.front());
    q.pop_front();
    return r;
  }
  std::vector<std::thread> threads;

  std::unique_lock<std::mutex> lock(){ return std::unique_lock<std::mutex>(m); }
  std::mutex m;
  std::deque<std::packaged_task<void()>> q;
  std::condition_variable cv;
};

Живой пример .

Используйте пул потоков;перейти к коду, который нуждается в потоках, с предварительно запущенными потоками (возможно, на основе аппаратного параллелизма).run задач.Ожидайте возвращенное будущее из методов запуска.

Это будет намного быстрее, чем раскручивание потоков по требованию.

...