С++ 11: std:: thread pooled?

В С++ 03 я использовал pthread с встроенным пулом потоков, который всегда поддерживал пару потоков (так как pthread_create медленный), таким образом я смог запускать потоки для небольших задач, не думая о производительности вопросы.

Теперь в С++ 11 имеем std::thread. Я предполагаю, что стандарт ничего не говорит о конкретной реализации, поэтому мой вопрос касается стандартных реализаций библиотек. Обычно ли они выбирают объединенный подход, когда построение std::thread является дешевым (и, например, не вызывает pthread_create в posix), или будет std::thread просто быть оберткой?

Другими словами, это пул потоков, который по-прежнему рекомендуется использовать в С++ 11, или мне нужно просто создать std::thread, когда мне это нужно, и оставить производительность до стандартной библиотеки?

Ответ 1

Как правило, std::thread должен быть минимальной оболочкой вокруг базового системного примитива. Например, если вы находитесь на платформе pthread, вы можете протестировать следующую программу, независимо от того, сколько потоков вы создаете, все они созданы с уникальными идентификаторами pthread_t (что подразумевает, что они создаются "на лету" и не заимствован из пула потоков):

#include <assert.h>
#include <mutex>
#include <set>
#include <thread>
#include <vector>

#include <pthread.h>

int main() {
  std::vector<std::thread> workers;
  std::set<long long> thread_ids;
  std::mutex m;
  const int n = 1024;

  for (int i = 0; i < n; ++i) {
    workers.push_back(std::thread([&] {
      std::lock_guard<std::mutex> lock(m);
      thread_ids.insert(pthread_self());
    }));
  }
  for (auto& worker : workers) {
    worker.join();
  }
  assert(thread_ids.size() == n);

  return 0;
}

Таким образом, пулы потоков все еще имеют смысл. Тем не менее, я видел видео, где члены комитета С++ обсуждали пулы потоков в отношении std::async (IIRC), но я не могу найти его прямо сейчас.

Ответ 2

A std::thread - это поток выполнения. Период. Откуда он получается, как он туда попадает, есть ли пул "реальных" потоков и т.д., Все это не имеет отношения к стандарту. Пока он действует как поток, это может быть std::thread.

Теперь хорошо, что std::thread - это реальный поток ОС, а не что-то, что вытаскивается из пула потоков или чего-то еще. Но С++ 11 теоретически позволяет реализовать std::thread как нечто, вырванное из пула.

Ответ 3

std::thread предполагается чрезвычайно дешево с точки зрения затрат на абстракцию, это низкоуровневый материал. Насколько я понимаю, стандартные реализации библиотек, вероятно, будут как можно более просто обтекать базовые механизмы ОС, поэтому вы можете предположить, что накладные расходы на создание потоков похожи или эквивалентны.

Я не знаю о каких-либо конкретных реализациях, но это мое второе понимание из чтения С++ Concurrency В действии, что стандарт предполагает, что они используют наиболее эффективный метод. Автор, несомненно, считал, что стоимость будет более или менее незначительной по сравнению с DIY.

Библиотека, подобная Boost концептуально, поэтому я предполагаю, что использование реализации Boost для выработки некоторых выводов не будет слишком надуманным.

В принципе, я не думаю, что есть ответ на ваш вопрос напрямую, потому что он просто не указан. Хотя мне кажется, что мы с большей вероятностью увидим очень тонкие реализации оболочек, я не думаю, что библиотекам запрещено использовать пулы потоков, если они предлагают преимущества эффективности.

Ответ 4

Во-первых, как вы уже упоминали, стандарт С++ в основном не определяет реализацию библиотеки. Но разработчик стандартной библиотеки С++ должен подчиняться правилу "как есть".

Например, это означает, что конструктор std::thread должен вести себя как , как если бы новый поток создавал ли тонкую оболочку базового API или эффективную реализацию, такую ​​как пул потоков. (здесь "поток" означает абстрактный поток выполнения в спецификации С++ 11, а не конкретный собственный поток ОС)

В реализации пула потоков;

  • Компилятор и библиотека С++ должным образом обрабатывают ресурсы, зависящие от потока С++ (т.е. переменную thread_local), и они должны работать совместно во время выполнения.
  • Даже если вышеуказанное условие выполнено, представляется невозможным совместное использование ресурсов ресурсов, специфичных для ОС (TLS для Windows, TSS для pthread и т.д.).

Итак, я предполагаю, что большая реализация std::thread - это просто оболочка базового API потоковой обработки.