Пул потоков TBB неожиданно увеличивается

У нас есть фрагмент кода, который использует TBB для создания задач для выполнения некоторой обработки. Это делается с использованием следующего кода TBB для инициализации пула потоков TBB:

tbb::task_scheduler_init(8);

Затем для каждой задачи, которую мы хотим создать, мы используем следующий код (где MainTask является производным от класса tbb::task):

task = new (tbb::task::allocate_root()) MainTask(theAction, theOutputData);
tbb::task::enqueue(*task);

Когда мы запускаем наш код, мы начинаем с пула потоков, который совпадает с количеством ядер (в нашем случае 8 потоков), как и ожидалось, но по мере того, как программа выполняет и порождает новые задачи TBB, как описано выше, количество потоков в некоторые случайные точки внезапно увеличиваются. После 40 минут выполнения программы количество потоков увеличивается с 8 до 15.

Почему это происходит? Разве TBB не должен поддерживать фиксированное количество рабочих потоков равным количеству ядер?


person S. J. Thunderstick    schedule 24.06.2016    source источник
comment
Возможно ли, что потоки создаются внешними по отношению к TBB? Потоки — это системный ресурс, их может создавать любая другая часть программы.   -  person lcs    schedule 24.06.2016
comment
Если вы new отредактировали task, где вы delete это сделаете?   -  person kangshiyin    schedule 24.06.2016


Ответы (1)


Как я уже сказал в другом ответе вам: не волнуйтесь :-)

TBB отлично справляется с предотвращением фактической переподписки - в вашей программе одновременно будут активны только 8 потоков. Хотя по разным причинам иногда требуется больше потоков, чем аппаратных ресурсов. Одним из примеров является tbb::task_arena без зарезервированных мастер-слотов, а другим недавним дополнением является класс tbb::global_control, который позволяет динамически изменять количество активных потоков в пуле. К сожалению, способ реализации TBB оставляет место для гонки данных. Это происходит, когда некоторые потоки возвращаются в пул потоков, чтобы немного поспать, в то время как поступает новая работа и запрашивает все 8 потоков для немедленного начала обработки; но эти потоки в промежуточном состоянии еще не учитываются в пуле потоков и вместо них создаются новые потоки.

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

Но опять же, не волнуйтесь, утечки ресурсов нет, потому что TBB жестко ограничивает максимальное количество потоков, которые он может создать таким образом. В зависимости от платформы это число варьируется где-то от 2x до 4x (хотя это внутренняя специфика реализации, которая постоянно меняется).

Тем не менее, я удивлен, что это зашло так далеко с 15 созданными потоками, и я понимаю ваши опасения. Команда TBB будет признательна, если вы поделитесь с ними репродуктором. Вы можете внести свой вклад в воспроизведение через форум TBB или сайт OSS.

person Anton    schedule 24.06.2016
comment
Спасибо за ваш полезный ответ, но у нас есть пара уточняющих вопросов. 1. Что такое репродуктор. 2. Как нам его создать и отправить? - person S. J. Thunderstick; 27.06.2016
comment
Воспроизведение @SJThunderstick — это минимальный тест, который воспроизводит проблему. Вы создаете тест и публикуете его на форуме или в качестве вклада. Но опять же, это не такая уж большая проблема — это не утечка и не переподписка. - person Anton; 27.06.2016