Многопоточная конкуренция за ресурсы

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

1 thread:
  Total thread time: 60 minutes.
  Total wall clock time: 60 minutes.

10 threads:
  Total thread time: 80 minutes. (Worked 33% longer)
  Total wall clock time: 18 minutes.  3.3 times speed up

20 threads
  Total thread time: 120 minutes. (Worked 100% longer)
  Total wall clock time: 12 minutes.  5 times speed up

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

Я уже изучил четыре столпа (ЦП, память, diskIO, сеть) как на компьютере приложения, так и на сервере базы данных. Память была исходным заявленным ресурсом, но теперь это исправлено (более 1 ГБ всегда свободно). ЦП колеблется между 30% и 70% в тесте с 20 потоками, так что много. diskIO практически отсутствует на компьютере приложения и минимален на сервере базы данных. Сеть действительно отличная.

Я также профилировал код с помощью redgate и не вижу методов, ожидающих блокировки. Это помогает, что потоки не разделяют экземпляры. Теперь я проверяю более тонкие элементы, такие как установление / объединение соединений с базой данных (если 20 потоков пытаются подключиться к одной и той же базе данных, должны ли они ждать друг друга?).

Я пытаюсь определить и устранить конфликт ресурсов, чтобы выполнение 20 потоков выглядело так:

20 threads
  Total thread time: 60 minutes. (Worked 0% longer)
  Total wall clock time: 6 minutes.  10 times speed up

Каковы наиболее вероятные источники (кроме большой четверки), на которые мне следует обратить внимание, чтобы найти это утверждение?


Код, который выполняет каждый поток, примерно:

Run ~50 compiled LinqToSql queries
Run ILOG Rules
Call WCF Service which runs ~50 compiled LinqToSql queries, returns some data
Run more ILOG Rules
Call another WCF service which uses devexpress to render a pdf, returns as binary data
Store pdf to network
Use LinqToSql to update/insert. DTC is involved: multiple databases, one server.

Службы WCF работают на одном компьютере, не имеют состояния и могут обрабатывать несколько одновременных запросов.


В машине 8 ЦП.


person Amy B    schedule 20.10.2011    source источник
comment
Предлагаем вам опубликовать код / ​​алгоритм, который вы пытаетесь распараллелить   -  person Mitch Wheat    schedule 20.10.2011
comment
Сколько процессоров у вашей машины?   -  person Hand-E-Food    schedule 20.10.2011
comment
Ваши операции в основном связаны с вводом-выводом, являются ли эти вызовы ввода-вывода асинхронными? если нет, попробуйте сделать их асинхронными, а затем посмотрите, получите ли вы какую-либо выгоду   -  person Ankur    schedule 20.10.2011
comment
Хорошо, я ценю этот инстинкт, помогающий мне решить проблему с производительностью. На этом этапе оценка проблемы предшествует ее решению. Я прошу измерить еще пару вещей.   -  person Amy B    schedule 20.10.2011
comment
сделайте несколько дампов стека во время процесса, и вы сами увидите раздор.   -  person bestsss    schedule 20.10.2011
comment
как вы настроили свои службы wcf? Вы используете контекстный режим экземпляра Single / PerSession / PerCall и каковы настройки для одновременных вызовов / экземпляров / сеанса?   -  person theburningmonk    schedule 20.10.2011


Ответы (3)


Вы описываете, что вам нужна масштабируемость на 100%, которая представляет собой соотношение 1: 1 между увеличением потоков s и уменьшением времени блокировки стены ... обычно это цель, но ее трудно достичь ...

Например, вы пишете, что нет конкуренции за память, потому что есть 1 ГБ свободного ... это ИМХО неправильное предположение ... конфликт памяти также означает, что если два потока попытаются выделить память, может случиться так, что нужно дождаться другое ... еще один момент, о котором следует помнить, - это прерывания, происходящие из-за GC, который временно замораживает все потоки ... GC можно немного настроить с помощью конфигурации (gcServer) - см. http://blogs.msdn.com/b/clyon/archive/2004/09/08/226981.aspx

Другой момент - это служба WCF, которая называется ... если она не может масштабироваться - например, рендеринг PDF - тогда это также форма конкуренции, например ...

Список возможных разногласий «бесконечен» ... и почти всегда по очевидным вопросам, о которых вы упомянули ...

РЕДАКТИРОВАТЬ - согласно комментариям:

Некоторые моменты для проверки:

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

РЕДАКТИРОВАТЬ 2:

Темы
Это темы из пула потоков? Если так, то вы не станете масштабироваться :-(

РЕДАКТИРОВАТЬ 3:

Потоки ThreadPool плохи для длительных задач, что имеет место в вашем сценарии ... подробности см.

Из http://www.yoda.arachsys.com/csharp/threads/printable.shtml

Для длительных операций следует использовать вновь созданные потоки; краткосрочные операции могут использовать пул потоков.

Если вам нужна максимальная производительность, стоит проверить CQRS и описанный реальный пример. как LMAX.

person Yahia    schedule 20.10.2011
comment
Только на 50% ускорение (20 потоков, 10-кратное ускорение). Мне повезло в том, что рендеринг PDF скоро будет исключен из процесса. Тем не менее, если потоки ожидают рендеринга этого pdf-файла, должен быть какой-то измеримый ресурс, на который я мог бы взглянуть, чтобы определить его, верно? Я обязательно найду способ измерить GC в Redgate. Я не прошу бесконечный список, просто следующие несколько пунктов для проверки. - person Amy B; 20.10.2011
comment
чтобы измерить ресурс, связанный с рендерингом PDF, вам нужно будет проверить что-то внутри библиотеки, используемой для рендеринга ... другой момент - это то, как обрабатываются ваши соединения / пулы соединений с БД - какой поставщик / конфигурация вы используете? Также проверьте планы выполнения (вы можете сделать это с помощью некоторого инструмента на стороне сервера БД) для всех используемых Linq2SQL - person Yahia; 20.10.2011
comment
Мне нужно было бы только заглянуть внутрь библиотеки, если бы она была заблокирована, верно? Если бы это была проблема с памятью, мне бы не пришлось заглядывать в библиотеку - я бы посмотрел на метрику на машине. Я использую пул соединений по умолчанию - что бы ни случилось, когда DataContext LinqToSql управляет соединением. Живу и дышу планами исполнения - это уже сделано. - person Amy B; 20.10.2011
comment
некоторые библиотеки PDF технически написаны так, что они работают только в одном потоке - я не знаю devexpress ... но я пробовал много библиотек PDF и не стал бы держать пари, что это всегда блокировка ... поскольку я никогда не используйте Linq2SQL для вещей, чувствительных к производительности. Я не могу много рассказать вам о пуле соединений в этом контексте ... вы используете SQL Server или Oracle или? Используете ли вы потоки из ThreadPool? - person Yahia; 20.10.2011
comment
Потоки ThreadPool не должны использоваться для длительных задач (как в этом случае) ... см. Мой РЕДАКТИРОВАНИЕ и ссылки там ... - person Yahia; 20.10.2011
comment
+1 за невероятную ссылку поддержки Microsoft о создании потока WCF. Он также описывает, какие показатели производительности следует отслеживать - очень полезно. - person Amy B; 20.10.2011

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

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

person Miguel    schedule 20.10.2011
comment
+1 за конфликт блокировки базы данных. Хотел бы я знать хороший способ его измерить. - person Amy B; 20.10.2011
comment
Вы можете запустить однопоточный тест и измерить все отдельные операции с БД. Затем сложите их вместе и скажем, из 60 минут всего 5 были потрачены на доступ к базе данных. Теперь вы знаете, что у вас всегда будет 5 минут, независимо от того, насколько эффективен ваш процесс. Таким образом, вы должны думать об этом как о вещах типа M + N, где M - время обработки, а N - время, потраченное на доступ к общим ресурсам, которые находятся вне вашего контроля. Вы можете улучшить M, используя многопоточность, но с N ничего не поделаешь, это всегда исправлено. - person Miguel; 20.10.2011

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

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

Вы никогда не увидите ускорения N x при переходе от 1 к N потоков. Это невозможно, потому что в конечном итоге все в ЦП является общим ресурсом, по которому будет определенная степень конкуренции.

Существует множество факторов, мешающих вам получить полное линейное ускорение. Вы предполагаете, что база данных, сервер, на котором запущена база данных, сеть, соединяющая ее с клиентом, клиентский компьютер, ОС и драйверы на обоих концах, подсистема памяти, дисковый ввод-вывод и все < / em> может работать в 20 раз быстрее при переходе от 1 до 20 потоков.

Два слова: продолжай мечтать.

Каждое из этих узких мест должно замедлить вас всего на несколько процентов, тогда общий результат будет примерно таким, как вы видите.

Я уверен, что вы можете настроить его немного лучше, но не ждите чудес.

Но одна вещь, которую вы можете искать, - это совместное использование строки кеша. Обращаются ли потоки к данным, которые очень близки к данным, используемым другими потоками? Как часто вы можете этого избежать?

person jalf    schedule 20.10.2011
comment
В настоящее время я нахожусь на ускорении N / 4, ищу ускорение N / 2. Потокам передается объект запроса с пакетом идентификаторов - оттуда они используют эти идентификаторы для загрузки своих собственных данных для работы. - person Amy B; 20.10.2011
comment
Ваше мнение о DB IO, DB CPU, DB Memory, Network capacity, Network ping, Client CPU, Client Memory, Client disk IO работает в 20 раз быстрее: уже проверил эти вещи - они не загружены. Я не ожидаю, что они будут работать в 20 раз быстрее, я рассчитываю использовать их больше, постоянно используя их все, а не по очереди. Они просто сидят там, где меньше возможностей. Что-то еще на пределе возможностей, и это то, что я ищу. - person Amy B; 20.10.2011