Я использую параллельную библиотеку задач из .NET framework 4 (в частности, Parallel.For
и Parallel.ForEach
), однако я получаю чрезвычайно посредственные ускорения при распараллеливании некоторых задач, которые выглядят так, как будто их следует легко распараллелить на двух- основной машина.
При профилировании системы, похоже, что происходит много синхронизации потоков из-за сборщика мусора. Я занимаюсь распределением объектов, поэтому мне интересно, как я могу улучшить concurrency, сводя к минимуму переписывание моего кода.
Например, есть некоторые методы, которые могут быть полезны в этой ситуации:
- Должен ли я попытаться вручную управлять GC?
- Должен ли я использовать
Dispose
? - Должен ли я закреплять объекты?
- Должен ли я делать другие небезопасные трюки с кодом?
Постскриптум:
Проблема заключается не в том, что GC работает слишком часто, а в том, что GC предотвращает параллельный параллельный запуск параллельного кода. Я также не считаю "распределять меньше объектов" приемлемым ответом. Для этого требуется переписать слишком много кода для работы с плохо рассортированным сборщиком мусора.
Я уже нашел один трюк, который помог общей производительности (с помощью gcServer), но это не помогло одновременно. Другими словами, Parallel.For
был только на 20% быстрее, чем последовательный цикл For, по неловко параллельной задаче.
POST-Постскриптум:
Хорошо, позвольте мне объяснить далее, у меня довольно большая и сложная программа: оптимизирующий интерпретатор. Это достаточно быстро, но я хочу, чтобы его производительность при задании параллельных задач (примитивных операций, встроенных в мой язык) масштабировалась так же, как доступно больше ядер. Во время оценок я выделяю много мелких объектов. Вся конструкция интерпретатора основана на всех значениях, полученных из одного полиморфного базового объекта. Это отлично работает в однопоточном приложении, но когда мы пытаемся применить параллельную библиотеку задач к параллельным вычислениям, нет никаких преимуществ.
После большого изучения того, почему параллельная библиотека задач не правильно распределяет работу по ядрам для этих задач, кажется, что виновником является GC. По-видимому, GC, похоже, действует как бутылочная горловина, потому что он делает некоторые из-за синхронизации потоков сцены, которые я не понимаю.
Мне нужно знать, что именно делает GC, что может привести к тому, что сильно параллельный код будет работать плохо, когда он будет много распределений, и как мы можем обойти это кроме только выделение меньшего количества объектов. Этот подход уже пришел ко мне и потребует значительного перезаписи большого количества кода.