Как улучшить производительность сборщика мусора .NET 4.0 в высококонкурентном коде?

Я использую параллельную библиотеку задач из .NET Framework 4 (специальноParallel.For а такжеParallel.ForEach) однако я получаю чрезвычайно посредственное ускорение при распараллеливании некоторых задач, которые выглядят так, как будто их легко распараллелить на двухъядерной машине.

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

Например, есть некоторые методы, которые могут быть полезны в этой ситуации:

Стоит ли пытаться управлять ГХ вручную?Должен ли я использоватьDispose?Должен ли я прикреплять объекты?Должен ли я делать другие опасные трюки кода?

Постскриптум:

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

Я уже нашел один трюк, который помог общей производительности (используя gcServer) но это не помогло одновременной работе. Другими словамиParallel.For был только на 20% быстрее, чем последовательный цикл For, в смущающе параллельной задаче.

POST-POSTSCRIPT:

Хорошо, позвольте мне объяснить подробнее, у меня довольно большая и сложная программа: оптимизирующий интерпретатор. Это достаточно быстро, но я хочу, чтобы его производительность выполнялась, когда выполняемые параллельные задачи (примитивные операции встроены в мой язык) хорошо масштабируются и доступно больше ядер. Я выделяю много мелких объектов во время оценки. Весь дизайн интерпретатора основан на том, что все значения получены из одного полиморфного базового объекта. Это прекрасно работает в однопоточном приложении, но когда мы пытаемся применить Task Parallel Library для параллельных вычислений, это не дает никаких преимуществ.

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

Что мне нужно знать, так это: что именно делает GC, что может привести к плохой работе сильно параллельного кода, когда он выполняет много выделений, и как мы можем обойти этоКроме как простовыделение меньшего количества объектов, Такой подход мне уже приходил в голову и потребовал бы значительного переписывания большого количества кода.

Ответы на вопрос(8)

Ваш ответ на вопрос