C # Эффективное разделение задач между ядрами - PullRequest
4 голосов
/ 20 августа 2010

Я работаю над небольшой симуляцией на моей 8-ядерной рабочей станции. Моделирование включает в себя моделирование взаимодействий между большим количеством независимых узлов. За один этап мне нужно выполнить серию простых атомарных операций с каждым узлом параллельно. Я использовал Parallel.ForEach из System.Threading.Tasks для одновременного применения операции к каждому узлу в списке всех узлов.

Это хорошо работает для 100-500 узлов, которые я использовал для тестирования. Нагрузка была сбалансирована очень хорошо с постоянно используемыми ядрами. К сожалению, когда я пытаюсь запустить симуляцию с основным набором данных (более 5000 узлов), все идет не так. Все 8 ядер большую часть времени остаются бездействующими: каждые несколько секунд они достигают 100%, а затем возвращаются к 1% использования. Через несколько минут возникает исключение OutOfMemoryException и происходит сбой программы.

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

Что я хотел бы спросить, так это действительно ли это хорошее решение проблемы, существуют ли лучшие из них, и как это должно быть реализовано в C #? Любые советы или комментарии приветствуются.

РЕДАКТИРОВАТЬ: Пример кода по запросу

Parallel.ForEach(listOfNodes, tempNode =>
{
   tempNode.foo();
} );

<snip>

void foo()
{
   foreach(myType bar in listOfmyType)
   {
       if (bar.isActive)
           setNodeActive();
   }
} 

Ответы [ 2 ]

3 голосов
/ 20 августа 2010

См. Этот поток, в котором обсуждается ограничение количества потоков, которые Parallel.For использует, чтобы избежать нехватки памяти:

http://connect.microsoft.com/VisualStudio/feedback/details/534571/parallel-foreach-may-create-an-inordinate-number-of-threads

Я бы попробовал установить ParallelOptions.MaxDegreeOfParallelism примерно на 500 и посмотреть, что произойдет.

2 голосов
/ 20 августа 2010

Я думаю, что идеальный метод был бы для модель для определения количества доступные ядра N, разбить список узлов в N сегментов, затем порождают N темы, давая каждому потоку отдельный раздел списка.

Именно это и делает Parallel.ForEach, поэтому должна быть другая проблема.

Будет очень сложно придумать лучшую систему (управление потоками) самостоятельно. Но вы можете использовать собственные планировщики в библиотеке задач.

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