Как сделать пул потоков в C++ TBB?

Возможно, я не измеряю это правильно, но у меня есть простой код, с которым я играю. Я не думаю, что это пул потоков, потому что если я делаю рабочий блок очень большим, то процессор увеличивается до 190-199%(у меня двухъядерный), но если я уменьшаю, рабочий блок меньше, но гораздо больше этих блоков, чем мой процессор запускает программу на 140-160%.

Я думаю, что происходит то, что потоки не объединяются в пул, а уничтожаются / создаются при необходимости, что замедляет работу программы, когда рабочие нагрузки меньше. я использую tbb::task_scheduler_init контролировать количество потоков, но я не знаю, как сказать tbb, чтобы сохранить поток в живых.

Вот некоторый код для иллюстрации проблемы:

#include <iostream>
#include <list>
#include <tbb/task.h>
#include <tbb/task_group.h>
//#include <stdlib.h>
#include "tbb/task_scheduler_init.h"
#include <boost/thread.hpp>

using namespace tbb;


long fib(long a)
{
    if (a < 2) return 1;

    return fib(a - 1) + fib(a - 2);
}

class PrintTask
{
public:
    void operator()()
    {
        //std::cout << "hi world!: " <<  boost::this_thread::get_id() << std::endl;

        fib(10);
    }
};

int main()
{
    tbb::task_scheduler_init init(4); //creates 4 threads
    task_group group;


    for (int i = 0; i < 2000000; ++i)
    {
        group.run(PrintTask());
        //std::cout << i << std::endl;
    }

    std::cout << "done" << std::endl;
    group.wait();

    return(0);
}

если вы измените fib на 40-45, работа для каждого потока станет большой, так что она достигнет полной скорости, но если вы используете текущую настройку, то задания очень малы, но многие из них выполняются.

примечание: я заметил, что, возможно, это связано с тем, что в приведенном выше случае он полностью использует мою память (4 гигабайта). Может ли замедление быть связано с этим? Кроме того, почему эта программа занимает всю память? Что хранится в памяти, если я просто вызываю поток, нет ли очереди, указывающей, сколько раз запустить, или он сохраняет весь поток в памяти для запуска?

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

Благодарю.

2 ответа

Решение

Вы не должны сильно беспокоиться об использовании процессора, а скорее смотрите на время выполнения и ускорение по сравнению с последовательным.

Есть несколько вещей, которые вы должны понимать о tbb:

Вы можете думать о том, что накладные расходы по планированию задачи в основном постоянны (это не совсем, но достаточно близко). Чем меньше объем работы, который вы запланировали, тем ближе подход к этой константе. Если вы приблизитесь к этой константе, вы не увидите ускорений.

Также потоки бездействуют, когда они не могут найти работу. Я предполагаю, что когда вы вызываете 'fib(10)', стоимость вызова run и необходимое распределение задач приближаются к стоимости фактического выполнения работы.

Точнее говоря, если у вас действительно есть 2000000 элементов с одной и той же задачей, вы, вероятно, должны вызывать parallel_for или parallel_for_each.

-Rick

Просто чтобы подчеркнуть последний пункт Рика, документы для task_group государство:

ПРЕДУПРЕЖДЕНИЕ. Создание большого количества задач для одной группы задач не масштабируется, поскольку создание задач становится узким местом в последовательном процессе. Если вы создаете несколько параллельных задач, попробуйте вместо этого использовать parallel_for (4.4) или parallel_invoke (4.12) или структурировать порождение как рекурсивное дерево.

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

Разработайте свой алгоритм так, чтобы тело часто добавляло больше, чем одну работу.... Чтобы добиться ускорения, размер зерна B::operator() должен быть порядка не менее ~100000 тактов. В противном случае внутренние издержки параллельного_для затопляют полезную работу.

Если вы ищете примеры нетривиальных TBB (за parallel_for учебник и т. д.), руководство по шаблонам TBB очень хорошее.

Другие вопросы по тегам