Я использую Concurrency::parallel_for()
библиотеки параллельных шаблонов Visual Studio 2010 (PPL) для обработки индексированного набора задач (как правило, индексный набор намного больше, чем количество потоков, которые могут выполняться одновременно). Каждая задача, прежде чем выполнять длительные вычисления, начинается с запроса частного ресурса рабочего хранилища у диспетчера общих ресурсов (в случае: представление файла с отображением памяти для конкретной задачи, но я думаю, что сюжетная линия была бы такой же, если бы каждая задача запросил выделение частной памяти из общей кучи).
Использование диспетчера общих ресурсов синхронизируется с Concurrency::critical_section
, и здесь начинается проблема: если первый поток/задача находится в критической секции, а вторая задача делает запрос, она должна ждать, пока запрос первой задачи не будет обработан. Затем PPL, по-видимому, думает: эй, этот поток ожидает, и есть еще задачи, поэтому создается другой поток, вызывающий до 870 потоков, в основном ожидающих в одном и том же диспетчере ресурсов.
Теперь, поскольку обработка запроса ресурсов является лишь небольшой частью всей задачи, я хотел бы сказать PPL в этой части, чтобы он придержал своих лошадей, ни один из ожиданий или совместных блоков не должен вызывать запуск новых потоков из указанного раздела. work-thread, и мой вопрос заключается в следующем: можно ли и как запретить определенному разделу потока создавать новые потоки, даже если он совместно блокируется. Я бы не возражал против создания новых потоков в других блоках дальше по пути обработки потока, но не более, чем, скажем, 2 * количество (гипер) ядер.
Альтернативы, которые я рассматривал до сих пор:
Ставьте задачи в очередь и обрабатывайте очередь из ограниченного числа потоков. Проблема: я надеялся, что parallel_for PPL сделает это сам.
Определите
Concurrency::combinable<Resource> resourceSet
; внеConcurrency::parallel_for
и инициализируйтеresourceSet.local()
один раз, чтобы уменьшить количество запросов ресурсов (за счет повторного использования ресурсов) до количества потоков (которое должно быть меньше количества задач). Проблема: эта оптимизация не предотвращает создание лишнего потока.Предварительно выделяйте необходимые ресурсы для каждой задачи вне цикла
parallel_for
. Проблема: это потребовало бы слишком много системных ресурсов, тогда как ограничение количества ресурсов количеством потоков/ядер было бы в порядке (если бы это не взорвалось).
Я прочитал http://msdn.microsoft.com/en-us/library/ff601930.aspx, раздел "Не блокировать повторно в параллельном цикле", но следуя приведенным здесь советам, параллельные потоки вообще отсутствовать.