вопрос о многопоточности для процесса больших партий - PullRequest
2 голосов
/ 25 января 2010

У нас есть пакетный процесс, состоящий из примерно 5 вычислений, которые происходят для каждой строки данных (всего 20 миллионов строк).Наш производственный сервер будет иметь около 24 процессоров с приличными процессорами.

Для нас критически важна производительность.Предполагая, что наши алгоритмы довольно эффективны, как лучше всего добиться максимальной производительности по времени?В частности, должны ли мы достичь более высокой производительности за счет многопоточности, использования пулов потоков и т. Д.?Кроме того, может ли быть полезным использование объекта Process для разделения пакета на несколько программ?

Ответы [ 7 ]

4 голосов
/ 25 января 2010

Несколько мыслей:

Во-первых, вам нужно определиться с «лучшим» - есть компромиссы, связанные с такой массовой обработкой. В частности, соображения касаются использования памяти, ввода-вывода и использования процессора. Сколько памяти требует каждый расчет. И так далее.

Предполагая, что вы являетесь единственным процессом на машине, у вас много памяти, и вы в первую очередь заинтересованы в оптимизации пропускной способности, вот несколько советов:

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

В дополнение к пулам потоков существует также Task Parallel Library , которая предлагает средства для упрощения разработки таких параллельных вычислений. Он специально разработан для масштабирования до количества ядер и оптимизации использования потоков. Также есть Parallel LINQ , что также может оказаться полезным.

2 голосов
/ 25 января 2010

В целом, если вы можете подождать .NET 4, PFX (параллельные расширения), вероятно, будет лучшей моделью.

до тех пор, пока не будет много процессов / потоков, начинающихся / заканчивающихся, т.е. используйте пул потоков (запуск процесса очень дорог, запуск потока очень дорог).

Простой подход: объединить расчеты в задания, которые должны быть выполнены за ~ 50 мс, а затем начать их очередь. Самое сложное - убедиться, что все закончено. Простое завершение будет иметь общий счетчик «завершено» с каждым заданием, увеличивающим его. Основной поток вращается при считывании счетчика, пока не достигнет ожидаемого конечного значения.

1 голос
/ 25 января 2010

Это во многом зависит от того, что составляют «5 расчетов». Если для выполнения этих 5 вычислений требуются значительные вычисления, многопоточность будет огромным преимуществом. Чем меньше объем работы, тем больше внимания нужно уделить разбиению, чтобы получить хороший выигрыш.

Учитывая, что это выполняется «для каждой строки данных», наиболее эффективный способ справиться с этим (если это возможно) - это обновить его непосредственно в вашей базе данных. Извлечение данных со стороны клиента, обработка и повторное заполнение будет намного медленнее, чем попытка выполнить вычисления непосредственно в БД. Большинство серверов баз данных сами по себе хорошо поддерживают многопоточность и хорошо справляются с оптимизацией обновлений, поэтому, если вам удастся обработать данные непосредственно в БД, вы получите лучшую производительность.

Если это невозможно, то я бы порекомендовал использовать Task Parallel Library , чтобы справиться с этим. Запуск в .NET 4 будет особенно полезен, так как кража работы, добавленная в пул потоков, даст вам лучшую общую пропускную способность.

0 голосов
/ 26 января 2010

Если вы используете SQL Server 2005/2008, рассмотрите возможность добавления своих вычислений в SQL Server в качестве функций CLR: http://msdn.microsoft.com/en-us/library/ms254498%28VS.80%29.aspx. Это намного быстрее, чем вычисления в T-SQL, и экономит ваши затраты на перемещение данных. в и из базы данных. SQL Server будет управлять потоками для вас. Вы также можете поэкспериментировать с открытием нескольких соединений, каждое из которых работает с различным набором строк, чтобы измерить влияние на производительность, время соединения и т. Д.

0 голосов
/ 25 января 2010

Я бы предложил сделать это в рамках процедуры базы данных, если это возможно. В противном случае, вероятно, не имеет значения, насколько эффективна ваша обработка на стороне клиента, время будет зависеть от сортировки данных по сети. Даже если вы запускаете процесс на той же машине, вы можете понести наказание за сериализацию всего через драйвер (предположительно ODBC). Если, конечно, вы не напишите собственную процедуру, которая может выполняться в адресном пространстве вашего сервера базы данных (если ваш сервер поддерживает это).

Полагаю, я бы предложил написать процедуру, которая принимает нижнюю и верхнюю границу для выбора записей, затем написать программу на стороне клиента, которая разветвляет несколько потоков, выделяет соединение с БД для каждого потока, а затем вызывает на стороне сервера. процедура с границами соответствующего размера (скажем, пять нитей с четырьмя миллионами рядов в каждой). Если ваш сервер БД многопоточный, то это должно дать вам приличную производительность.

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

0 голосов
/ 25 января 2010

Только детальная оценка может выявить лучший способ оптимизировать их задачу, но, безусловно, использование пула потоков может принести улучшения. Откройте для себя наиболее распространенные задачи и разделите их в пуле. Важно отметить, ключевые способы измерения производительности, только тогда можно будет узнать, где находятся узкие места и где можно улучшить.

0 голосов
/ 25 января 2010

Threadpools - это безопасный и простой способ сделать это - для пула доступно максимум 64 одновременных потока (на самом деле это предел WaitHandles). Использование объекта Process просто создает новые проблемы и сложности, связанные с отладкой, которые не стоят предполагаемых компромиссов, особенно с учетом того, что любая ценность, которую вы получите, будет получена из параллелизма, который даст вам пул.

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