У меня есть очередь с элементами, которые нужно обработать. Я хочу обрабатывать эти элементы параллельно. В каждом элементе будет несколько разделов, которые необходимо синхронизировать. В любой момент времени может быть максимум num_threads бегущие темы.
Я предоставлю шаблон чтобы дать вам представление о том, чего я хочу достичь.
queue q
process_element(e)
{
lock()
some synchronized area
// a matrix access performed here so a spin lock would do
unlock()
...
unsynchronized area
...
if( condition )
{
new_element = generate_new_element()
q.push(new_element) // synchonized access to queue
}
}
process_queue()
{
while( elements in q ) // algorithm is finished condition
{
e = get_elem_from_queue(q) // synchronized access to queue
process_element(e)
}
}
я могу использовать
Основные проблемы, которые у меня есть
Мой план в отношении Intel TBB concurrent_queue для контейнера очереди. Но тогда я смогу использовать функции pthreads (мьютексы, условия)? Давайте предположим, что это работает (это должно). Тогда как я могу использовать pthreads, чтобы иметь максимальное количество num_threads в один момент времени? Я думал создать потоки один раз, а затем, после того, как один элемент — процессы, получить доступ к очереди и получить следующий элемент. Однако это более сложно, потому что я не могу гарантировать, что если в очереди нет элемента, алгоритм завершен.
Мой вопрос
Прежде чем я начну внедрять, я хотел бы знать, есть ли простой способ использовать intel tbb или pthreads для получения желаемого поведения? Точнее параллельно обрабатывать элементы из очереди
Замечания: Я пытался использовать задачи, но безуспешно.
Во-первых, pthreads дает вам мобильность, от которой трудно уйти. Следующее представляется верным из вашего вопроса — дайте нам знать, если это не так, потому что ответ изменится:
1) У вас есть многоядерный процессор (ы), на котором вы выполняете код
2) хочешь иметь не больше чем num_threads темы из-за (1)
Предполагая, что вышеизложенное верно, следующий подход может вам помочь:
В зависимости от того, как часто вы добавляете / удаляете элементы из очереди, вы можете использовать что-то более легкое, чем pthread_mutex _…, чтобы ставить в очередь / исключать из очереди элементы. Здесь вы можете использовать более специфичную для машины конструкцию.
TBB совместим с другими пакетами потоков.
TBB также подчеркивает масштабируемость. Поэтому, когда вы переносите свою программу с двухъядерного на четырехъядерное ядро, вам не нужно настраивать свою программу. При параллельном программировании данных производительность программы увеличивается (масштабируется) по мере добавления процессоров.
Cilk Plus — это еще одна среда выполнения, которая обеспечивает хорошие результаты.
www.cilkplus.org
Поскольку pThreads является низкоуровневой ведущей библиотекой, вам нужно решить, какой уровень управления вам нужен в вашем приложении, потому что он предлагает гибкость, но требует больших затрат с точки зрения усилий программиста, времени отладки и затрат на обслуживание.
Я рекомендую посмотреть на tbb::parallel_do
, Он был разработан для параллельной обработки элементов из контейнера, даже если сам контейнер не является параллельным; то есть parallel_do
работает с std::queue
правильно без какой-либо пользовательской синхронизации (конечно, вам все равно нужно защитить свой матричный доступ внутри process_element()
, Более того, с parallel_do
Вы можете добавить больше работы на лету, которая выглядит как то, что вам нужно, а process_element()
создает и добавляет новые элементы в рабочую очередь (единственное предупреждение заключается в том, что вновь добавленная работа будет обработана немедленно, в отличие от помещения в очередь, которая откладывает обработку до всех «старых» элементов). Кроме того, вам не нужно беспокоиться о прекращении: parallel_do
завершится автоматически, как только будут обработаны все начальные элементы очереди и новые элементы, созданные на лету.
Однако если, помимо самих вычислений, рабочую очередь можно одновременно передавать из другого источника (например, из потока обработки ввода / вывода), тогда parallel_do
не подходит. В этом случае, возможно, имеет смысл взглянуть на parallel_pipeline
или, лучше, график потока TBB.
Наконец, приложение может контролировать количество активных потоков с помощью TBB, хотя это не рекомендуемый подход.