Поточная обработка по сравнению с единственным потоком

Всегда гарантируется, что многопоточное приложение работало бы быстрее, чем единственное потоковое приложение?

У меня есть два потока, который заполняет данные из источника данных, но различных объектов (например: база данных, от двух различных таблиц), кажется, что единственная потоковая версия приложения работает быстрее, чем версия с двумя потоками.

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

что лучшие практики должны поднять ЦП и полностью использовать его?

Я надеюсь, что это не неоднозначно.

23
задан John Saunders 25 May 2010 в 07:04
поделиться

7 ответов

Может помочь аналогия.

У вас есть куча писем, которые вам нужно доставить по разным адресам в городе. Итак, вы нанимаете парня с мотоциклом для доставки ваших писем.

Светофоры в вашем городе - идеальные светофоры. Они всегда зеленые, если только кто-то не находится на перекрестке.

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

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

Это быстрее? Нет, конечно, нет. Это медленнее . Добавление большего количества потоков ничего не ускоряет. Нити не волшебство . Если процессор может выполнять миллиард операций в секунду, добавление еще одного потока не делает сразу доступным еще один миллиард операций в секунду. Скорее, он крадет ресурсов у других потоков.Если мотоцикл может двигаться со скоростью 100 миль в час, остановка мотоцикла и посадка другого водителя не ускорят его! Очевидно, что в среднем по этой схеме письма не доставляются быстрее, они просто доставляются в другом порядке.

Хорошо, а что, если нанять двух водителей и два мотоцикла? Теперь у вас есть два процессора и один поток на процессор, так что это будет быстрее, верно? Нет, потому что мы забыли про светофор. Раньше в каждый момент времени на высокой скорости ехал только один мотоцикл. Теперь есть два водителя и два мотоцикла, а это значит, что теперь иногда одному из мотоциклов придется ждать, потому что другой находится на перекрестке. Опять же, добавление большего количества потоков замедляет вас , потому что вы тратите больше времени на борьбу с блокировками. Чем больше процессоров вы добавите, тем хуже будет; вы в конечном итоге все больше и больше времени проводите в ожидании на красный свет и все меньше и меньше времени проводите за передачей сообщений.

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

Предположим, вы сделали механизмы быстрее - теперь у вас больше процессоров, больше потоков и более быстрые процессоры. Всегда ли это делает его быстрее? НЕТ. Часто это не так. Увеличение скорости процессора может сделать многопоточные программы медленнее . Опять же, подумайте о пробках.

Предположим, у вас есть город с тысячами водителей и шестьюдесятью четырьмя мотоциклами, все водители бегают туда-сюда между мотоциклами, причем некоторые мотоциклы на перекрестках блокируют другие мотоциклы. Теперь вы заставляете все эти мотоциклы ездить быстрее. Это помогает? Что ж, в реальной жизни, когда вы едете, добираетесь ли вы в два раза быстрее на Porsche, чем на Honda Civic? Конечно, нет; большую часть времени, путешествуя по городу, вы застряли в пробке .

Если вы умеете водить быстрее, вам часто приходится ждать в пробке дольше , потому что вы быстрее въезжаете в пробку. Если все едут к перегрузке быстрее, то перегрузка ухудшается .

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

60
ответ дан 29 November 2019 в 00:51
поделиться

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

2
ответ дан 29 November 2019 в 00:51
поделиться

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

Приложения с ограничением ввода-вывода - еще один хороший пример, упомянутый выше.

0
ответ дан 29 November 2019 в 00:51
поделиться

Мое мнение

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

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

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

...кажется, что однопоточная версия приложения работает быстрее, чем версия с двумя потоками.

Вы проводили какой-либо анализ производительности? Если нет, то то, что вы заметили, не имеет никакого значения.

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

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


Непосредственно из Wikipedia:

Преимущества

Некоторые преимущества включают:

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

Недостатки

Некоторые критические замечания по поводу многопоточности включают:

  • Несколько потоков могут мешать друг другу при совместном использовании аппаратных ресурсов, таких как кэш или буферы трансляции (translation lookaside buffers, TLBs).
  • Время выполнения однопоточной программы не улучшается, а может ухудшаться, даже если выполняется только один поток. Это связано с более медленными частотами и/или дополнительными стадиями конвейера, которые необходимы для размещения аппаратных средств переключения потоков.
  • Аппаратная поддержка многопоточности более заметна для программного обеспечения, поэтому требует больше изменений как в прикладных программах, так и в операционных системах, чем многопроцессорность.

Обновление

Кроме того, сервер базы данных находится на той же машине, на которой выполняется код. это не sql сервер. это nosql dbms. поэтому, пожалуйста, не предполагайте ничего о сервере базы данных.

Некоторые системы NoSQL основаны на дисках, а чтение с диска из нескольких потоков почти гарантированно снижает производительность. Жесткий диск может быть вынужден перемещать головку в разные сектора диска при переходе между потоками, а это плохо!

Я понимаю, что вы хотели сказать. это скорость ввода-вывода. но все же это одна и та же машина. Почему IO такой медленный?

Ваша система NoSQL может быть дисковой, поэтому все ваши данные хранятся на диске, а не загружаются в память (как SQL Server). Кроме того, подумайте об архитектуре: диск - это кэш для оперативной памяти, оперативная память - кэш для кэша процессора, а кэш процессора - для регистров процессора. Итак, диск -> оперативная память -> кэш процессора -> регистры, есть 3 уровня кэширования, прежде чем вы доберетесь до регистров. В зависимости от того, сколько данных вы используете, вы можете получить много промахов кэша для обоих ваших потоков на каждом из этих уровней... промах кэша в кэше CPU загрузит больше данных из оперативной памяти, промах кэша в оперативной памяти загрузит больше данных с диска, все это приводит к снижению пропускной способности.

в других критиках "создать достаточно потоков для использования ..." создание многих потоков также займет время. Верно?

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

9
ответ дан 29 November 2019 в 00:51
поделиться

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

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

3
ответ дан 29 November 2019 в 00:51
поделиться

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

Я бы предложил писать масштабируемые приложения в SEDA (Staged Event Driven Architecture), когда система состоит из нескольких (5-15) компонентов и каждый компонент имеет свою очередь сообщений с ограниченным пулом потоков. Вы можете настраивать размер пулов и даже применять алгоритмы, изменяющие размер пула потоков, чтобы сделать одни компоненты более производительными, чем другие (поскольку все компоненты используют одни и те же процессоры). Вы можете настраивать размер пулов для конкретного оборудования, что делает приложения SEDA чрезвычайно настраиваемыми.

0
ответ дан 29 November 2019 в 00:51
поделиться

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

1
ответ дан 29 November 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: