2010-02-18 1 views
1

У меня есть следующая ситуация:boost :: thread_group - можно ли вызвать create_thread после join_all?

Я создаю экземпляр 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 на thread_group после вызов 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

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

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

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

+0

Код работал так, как было (как в моем предлагаемом решении), но я не был уверен, что он стабилен. Я внедрил версию, которая явно удаляет мертвые потоки после join_all. Это не самая эффективная реализация, но теперь это будет сделано (как описано здесь: http://groups.google.com/group/boost-list/browse_thread/thread/1ff81e265a981b5b/76f124feb9143ba9?lnk=gst&q=thread_group # 76f124feb9143ba9) Я также рассмотрю реализацию решения производителя-потребителя (спасибо). – utnapistim

 Смежные вопросы

  • Нет связанных вопросов^_^