Многопоточность против многопроцессорности - PullRequest
28 голосов
/ 17 июня 2011

Я новичок в этом виде программирования и мне нужна ваша точка зрения.

Мне нужно создать приложение, но я не могу заставить его вычислить достаточно быстро.Я уже пробовал Intel TBB, и он прост в использовании, но я никогда не использовал другие библиотеки.

В многопроцессорном программировании я читаю об OpenMP и Boost для многопоточности, но я не знаю ихплюсы и минусы.

В C ++, когда многопоточное программирование выгодно по сравнению с многопроцессорным программированием и наоборот? Что лучше всего подходит для сложных вычислений или запуска многих задач ...?Каковы их плюсы и минусы, когда мы создаем приложение, разработанное с их помощью?И, наконец, с какой библиотекой лучше всего работать?

Ответы [ 4 ]

54 голосов
/ 17 июня 2011

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

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

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

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

21 голосов
/ 17 июня 2011

Есть несколько важных моментов, которые, как я считаю, должны быть добавлены к превосходному ответу @ Jason.

Во-первых, многопоточность не всегда является иллюзией даже на одном процессоре - есть операции, которые не связаны с процессором. В основном это I / O - диск, сеть, терминал и т. Д. Базовая форма для такой операции: блокировка или синхронная , т.е. Ваша программа ждет, пока операция не будет завершена, а затем продолжается. Во время ожидания ЦП переключается на другой процесс / поток.

если у вас есть что-то, что вы можете сделать в течение этого времени (например, фоновые вычисления во время ожидания ввода пользователя, обработки другого запроса и т. Д.), У вас есть два основных варианта:

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

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

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

  • с асинхронным вводом / выводом логика логики программы менее очевидна, и ее трудно отслеживать и отлаживать. Однако вы избегаете проблем thread-security .
  • с потоками, задача состоит в написании поточно-безопасных программ. Ошибки безопасности потоков - это неприятные ошибки, которые довольно сложно воспроизвести. Чрезмерное использование блокировки может привести к снижению производительности вместо повышения производительности.

(подходит к мультиобработке)

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

В Linux / Unix процессы намного проще. Кроме того, (AFAIK) потоки в Linux реализованы фактически как внутренние процессы, поэтому нет никакой выгоды в переключении контекста между потоками и процессами. Тем не менее, вам необходимо использовать IPC (межпроцессное взаимодействие) в виде общей памяти, каналов, очереди сообщений и т. Д.

В более легкой заметке посмотрите FAQ по SQLite , в котором объявлено, что «потоки - это зло»! :)

3 голосов
/ 17 июня 2011

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

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

Я не использовал TBB, но я использовал IPP и нашел его эффективным и хорошо продуманным. Буст портативный.

0 голосов
/ 15 июня 2013

Просто хотел отметить, что парадигма потокового программирования (http://www.jpaulmorrison.com/fbp) - это естественно многопрограммный / многопроцессорный подход к разработке приложений.Он обеспечивает согласованное представление приложения от высокого уровня до низкого уровня.Реализации Java и C # используют преимущества всех процессоров на вашем компьютере, но более старая реализация C ++ использует только один процессор.Тем не менее, он может быть довольно легко расширен для использования BOOST (или, я полагаю, pthreads) с помощью блокировки соединений.Я начал преобразовывать его, чтобы использовать волокна, но я не уверен, есть ли смысл продолжать этот маршрут.:-) Обратная связь будет оценена.Кстати, реализации Java и C # могут даже взаимодействовать с использованием сокетов.

...