В C ++ 03 я использовал pthread со встроенным пулом потоков, который всегда поддерживал работу нескольких потоков (так как pthread_create
медленно), таким образом, я смог запустить потоки для небольших задач, не думая о проблемах производительности.
Теперь в C ++ 11 мы имеем std::thread
, Я предполагаю, что стандарт ничего не говорит о конкретной реализации, поэтому мой вопрос касается реализаций стандартной библиотеки. Они вообще выбирают объединенный подход, где строительство std::thread
s дешево (и, например, не звонит pthread_create
на posix), или будет std::thread
просто быть оберткой?
Другими словами, пул потоков все еще рекомендуется в C ++ 11, или я должен просто создать std::thread
когда мне нужно и оставить производительность до стандартной библиотеки?
В общем-то, 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;
}
Так что пулы потоков все еще имеют смысл. Тем не менее, я видел видео, где члены комитета C ++ обсуждали пулы потоков относительно std::async
(IIRC), но я не могу найти это прямо сейчас.
std::thread
это поток исполнения. Период. Откуда оно берется, как оно туда попадает, есть ли какой-то пул «реальных» потоков и т. Д., Все это не имеет отношения к стандарту. Пока это действует как нить, это может быть std::thread
,
Теперь шансы хороши, что std::thread
это реальный поток ОС, а не что-то извлеченное из пула потоков или чего-то еще. Но C ++ 11 теоретически позволяет std::thread
быть реализованным как нечто извлеченное из пула.
std::thread
должен быть очень дешевым с точки зрения затрат на абстракцию, это вещи низкого уровня. Насколько я понимаю, реализации стандартных библиотек, вероятно, собираются просто как можно точнее обернуть базовые механизмы ОС, чтобы можно было предположить, что накладные расходы на создание потоков будут аналогичными или эквивалентными.
Я не знаю о каких-либо конкретных реализациях, но это мое понимание из вторых рук от чтения C ++ параллелизм в действии что стандарт предлагает использовать наиболее эффективный метод. Автор, конечно, думал, что стоимость будет более или менее незначительной по сравнению с DIY.
Библиотека концептуально похожа на Boost, поэтому я полагаю, что использование Boost для некоторых выводов не будет слишком надуманным.
В принципе, я не думаю, что есть ответ на ваш вопрос напрямую, потому что он просто не указан. Хотя мне кажется, что мы с большей вероятностью увидим очень тонкие реализации-оболочки, я не думаю, что авторам библиотек запрещено использовать пулы потоков, если это дает преимущества в эффективности.
Во-первых, как вы упомянули, стандарт C ++ в основном не определяет реализацию библиотеки.
Но реализатор стандартной библиотеки C ++ должен подчиняться правилу «как будто».
Например, это означает, что конструктор std::thread
должен вести себя как будто Новый поток создан, будь то тонкая оболочка базового API или эффективная реализация, такая как пул потоков. (здесь «поток» означает абстрактный нить исполнения в спецификации C ++ 11, а не конкретная нить нативной ОС)
О реализации пула потоков;
thread_local
переменная), и они должны работать вместе во время выполнения.Итак, я предполагаю, что большинство std::thread
реализация — это просто оболочка базового API потоков.