Я работаю над небольшой симуляцией на моей 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();
}
}