Как сформулировать разницу между асинхронным и параллельным программированием?

141

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

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

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

Мэтт Шерман
источник
Я написал сообщение в блоге о взаимосвязи асинхронного и параллельного программирования - anat-async.blogspot.com/2018/08/…
Алексей Кайгородов
6
параллелизм - это когда все происходит одновременно. Асинхронность - это когда вы не беспокоитесь, ожидая продолжения результата действия. Вы просто ложитесь спать, и в какой-то момент приходит результат, звонит в колокольчик, вы просыпаетесь и продолжаете оттуда. Асинхронное выполнение может выполняться последовательно только в одном потоке. (это в значительной степени то, что делает javascript)
Thanasis

Ответы:

88

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

Возьмем, к примеру, рендеринг кадров 3D-анимации. На рендеринг анимации уходит много времени, поэтому, если бы вы запускали этот рендеринг из своего программного обеспечения для редактирования анимации, вы должны были убедиться, что он работает асинхронно, чтобы он не блокировал ваш пользовательский интерфейс, и вы могли продолжать делать другие вещи. Теперь каждый кадр этой анимации тоже можно рассматривать как отдельную задачу. Если у нас есть несколько процессоров / ядер или несколько компьютеров, мы можем отображать несколько кадров параллельно, чтобы ускорить общую рабочую нагрузку.

CodeMan
источник
Дай мне посмотреть, получу ли я это. Параллельные задачи рендеринга различных кадров должны быть распределены между несколькими процессорами / ядрами. Это не имеет никакого отношения к срокам завершения задачи или к тому, блокирует ли эта задача что-то еще. Это просто означает, что несколько процессоров будут делать это вместе и делать результат доступным, как если бы он работал на одном сверхбыстром процессоре. Правильно?
1
«На рендеринг анимации уходит много времени, поэтому, если бы вы запустили этот рендеринг из своего программного обеспечения для редактирования анимации, вы бы обязательно (...)». Какие?
Что касается части 3D-анимации: во-первых, вы НИКОГДА не запускаете программу 3D-графики с генерацией кадров на CPU - любой здравомыслящий человек сразу же предложит использовать GPU. Во-вторых, если мы сделаем это (что крайне не рекомендуется), мы будем использовать таймер для измерения количества кадров, которые мы можем визуализировать, иначе мы могли бы просто создать стек незавершенных задач вызова рендеринга. Но ваша точка зрения совершенно верна для большинства приложений 2D-рендеринга, которые рендерит на основе событий ввода для каждого пользователя.
ワ イ き ん ぐ
1
Асинхронный и неблокирующий - разные парадигмы.
Marquis of Lorne
75

Я считаю, что главное различие заключается между параллелизмом и параллелизмом .

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

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

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

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

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

Асинхронный вызов и обратные вызовы - это просто механизм, который позволяет программисту выражать параллелизм. Учтите, что хорошо известные шаблоны проектирования параллельного программирования, такие как master / worker или map / reduce, реализуются фреймворками, которые используют такие механизмы более низкого уровня (async) для реализации более сложных централизованных взаимодействий.

игон
источник
39

Эта статья очень хорошо объясняет это: http://urda.cc/blog/2010/10/04/asynchronous-versus-parallel-programming

Это касается асинхронного программирования:

Асинхронные вызовы используются для предотвращения «блокировки» в приложении. [Такой] вызов будет отделяться от уже существующего потока (такого как поток ввода-вывода) и выполнять свою задачу, когда это возможно.

это о параллельном программировании:

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

и это в итоге:

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

Павел
источник
3
Эта статья> все ответы здесь (кроме этого, конечно!)
FellyTone84
1
Спасибо за ссылку. Итак ... в общем , используйте асинхронные вызовы при связи от пользовательского интерфейса к серверу (или от клиента к веб-службе). Используйте параллельную обработку потоков на сервере или в конце веб-службы, а также на бизнес-уровне.
goku_da_master
18

Мое основное понимание:

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

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

Это, наверное, сложнее, но я думаю, что это основное различие.

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

Я склонен думать о разнице в следующих терминах:

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

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

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

Леонард Х. Мартин
источник
14

async : сделайте это самостоятельно в другом месте и уведомите меня, когда завершите (обратный вызов). К тому времени я смогу продолжать заниматься своим делом.

введите описание изображения здесь

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

введите описание изображения здесь

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

Серкан
источник
11

Это вопрос порядка исполнения.

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

Если A параллельно B, то события в A происходят одновременно с событиями в B. Однако порядок выполнения все еще может быть определен.

Возможно, трудность в том, что слово «асинхронный» двусмысленно.

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

Моя бригада горничных работает параллельно, когда каждая из них моет разные окна.

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

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

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

Пистолет Гатлинга с кулачковым механизмом можно рассматривать как параллельный, но все на 100% синхронно, поэтому создается впечатление, что один процесс продвигается вперед.

Ричард
источник
9

Почему асинхронный?

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

Почему параллельное программирование?

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

Код-EZ
источник
6

Асинхронный. Допустим, вы являетесь контактным лицом для своего клиента, и вам нужно быстро реагировать, т.е. вам нужно сообщать о статусе, сложности операции, требуемых ресурсах и т. Д. По запросу. Теперь у вас есть трудоемкая операция, которую нужно выполнить, и, следовательно, вы не можете ею заниматься, поскольку вам нужно реагировать на клиента 24/7. Следовательно, вы делегируете трудоемкую операцию кому-то другому, чтобы вы могли быстро реагировать. Это асинхронно.

Параллельное программирование Допустим, у вас есть задача прочитать, скажем, 100 строк из текстового файла, а чтение одной строки занимает 1 секунду. Следовательно, вам потребуется 100 секунд, чтобы прочитать текстовый файл. Теперь вы беспокоитесь, что клиент должен ждать 100 секунд для завершения операции. Следовательно, вы создаете еще 9 клонов и заставляете каждый из них читать 10 строк из текстового файла. Теперь на чтение 100 строк уходит всего 10 секунд. Следовательно, у вас лучшая производительность.

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

Варун Шридхар
источник
4

Асинхронный: выполнение метода или задачи в фоновом режиме без блокировки. Не обязательно запускать отдельный поток. Использует переключение контекста / планирование времени.

Параллельные задачи: каждая задача выполняется параллельно. Не использует переключение контекста / планирование времени.

Адитья Бокаде
источник
4

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

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

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

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

Для нашей метафоры связь состоит в том, что ОС всегда перемешивает карты перед отправкой их процессору. Если ваша стопка карт не зависит от другой стопки, вы не заметите, что ваша стопка перестала выбираться, когда другая стопка стала активной. Так что, если вам все равно, это не имеет значения.

Однако, если вам все равно (например, существует несколько процессов - или стопок карт - которые зависят друг от друга), то перетасовка ОС испортит ваши результаты.

Написание асинхронного кода требует обработки зависимостей между порядком выполнения, независимо от того, каким в конечном итоге будет этот порядок. Вот почему используются такие конструкции, как «обратные вызовы». Они говорят процессору: «Следующее, что нужно сделать, это сообщить другому стеку, что мы сделали». Используя такие инструменты, вы можете быть уверены, что другой стек получит уведомление до того, как он разрешит ОС выполнять какие-либо другие свои инструкции. («Если called_back == false: send (no_operation)» - не уверен, что это действительно так, но логически я думаю, что это согласованно.)

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

Не уверен, что это помогает, но я всегда нахожу полезными несколько объяснений. Также обратите внимание, что асинхронное выполнение не ограничивается отдельным компьютером и его процессорами. Вообще говоря, он имеет дело со временем или (даже в более общем смысле) с порядком событий. Поэтому, если вы отправляете зависимый стек A на сетевой узел X, а его связанный стек B - на Y, правильный асинхронный код должен учесть ситуацию, как если бы он работал локально на вашем ноутбуке.

Philrea
источник
2

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

На высоком уровне, как популярный сервер NGINX и известная библиотека Python Tornado , они оба полностью используют асинхронную парадигму, которая заключается в том, что однопоточный сервер может одновременно обслуживать тысячи клиентов (некоторые IOloop и обратный вызов ). Использование ECF (управление исключениями), которое могло бы реализовать парадигму асинхронного программирования. поэтому асинхронный иногда не делает что-то одновременно, но некоторая работа, связанная с io, асинхронная может действительно повысить производительность.

Параллельная парадигма всегда относится многопоточность, и многопроцессорные. Это может полностью использовать многоядерные процессоры, действительно одновременно.

Ideoutrea
источник
-1

Резюме всех вышеперечисленных ответов

  1. параллельные вычисления:

▪ решает проблему пропускной способности. Обеспокоен разбиением большой задачи на более мелкие части

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

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

  1. асинхронный:

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

▪ связано с потоком (требуется многопоточность)

Потоки (с использованием Thread, Runnable, Executor) - один из основных способов выполнения асинхронных операций в Java.

Вишнав Рамеш Триссур
источник