boost :: thread_group - нормально ли вызывать create_thread после join_all? - PullRequest
1 голос
/ 18 февраля 2010

У меня следующая ситуация:

Я создаю экземпляр boost :: thread_group, затем создаю потоки для параллельной обработки некоторых данных, затем join_all в потоках.

Сначала я создалпотоки для каждого элемента X данных, например, так:

// begin = someVector.begin();
// end = someVector.end();
// batchDispatcher = boost::function<void(It, It)>(...);

boost::thread_group     processors;

// create dispatching thread every ASYNCH_PROCESSING_THRESHOLD notifications
while(end - begin > ASYNCH_PROCESSING_THRESHOLD)
{
    NotifItr split = begin + ASYNCH_PROCESSING_THRESHOLD;

    processors.create_thread(boost::bind(batchDispatcher, begin, split));
    begin = split;
}

// create dispatching thread for the remainder
if(begin < end)
{
    processors.create_thread(boost::bind(batchDispatcher, begin, end));
}

// wait for parallel processing to finish
processors.join_all();

, но у меня есть проблема с этим: когда у меня много данных, этот код генерирует много потоков (> 40 потоков), который сохраняетпроцессор занят контекстами переключения потоков.

У меня такой вопрос: можно ли вызвать create_thread в группе потоков после вызова join_all.

То естьМогу ли я изменить свой код на это?

boost::thread_group     processors;
size_t                  processorThreads = 0; // NEW CODE

// create dispatching thread every ASYNCH_PROCESSING_THRESHOLD notifications
while(end - begin > ASYNCH_PROCESSING_THRESHOLD)
{
    NotifItr split = begin + ASYNCH_PROCESSING_THRESHOLD;

    processors.create_thread(boost::bind(batchDispatcher, begin, split));
    begin = split;

    if(++processorThreads >= MAX_ASYNCH_PROCESSORS) // NEW CODE
    {                               // NEW CODE
        processors.join_all();      // NEW CODE
        processorThreads = 0;       // NEW CODE
    }                               // NEW CODE
}

// ... 

Кто имеет опыт работы с этим, спасибо за понимание.

1 Ответ

1 голос
/ 23 февраля 2010

Я считаю, что это невозможно. Решение, которое вы действительно хотите, может заключаться в реализации производитель-потребитель или мастер-работник (основной «главный» поток делит работу на несколько задач фиксированного размера, создает пул «рабочих» потоков и отправляет одну задачу каждому работнику, пока все задачи не будут выполнены).

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

Еще один вариант, который не так хорош и интересен - это присоединяться к одному потоку за раз. Вы можете иметь вектор с 4 активными нитями, присоединиться к одному и создать другой. Проблема этого подхода заключается в том, что вы можете тратить время на обработку, если ваши задачи неоднородны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...