Учебники

Параллелизм против параллелизма

И параллелизм, и параллелизм используются по отношению к многопоточным программам, но существует много путаницы между сходством и различием между ними. Большой вопрос в этом отношении: параллелизм параллелизм или нет? Хотя оба термина выглядят довольно схожими, но ответ на поставленный выше вопрос — НЕТ, параллелизм и параллелизм не совпадают. Теперь, если они не одинаковы, то в чем их основная разница?

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

Параллельность в деталях

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

совпадение

Уровни параллелизма

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

Низкоуровневый параллелизм

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

Средний уровень параллелизма

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

Параллелизм высокого уровня

В этом параллелизме не используются ни явные атомарные операции, ни явные блокировки. Python имеет модуль concurrent.futures для поддержки такого рода параллелизма.

Свойства параллельных систем

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

Свойство правильности

Свойство корректности означает, что программа или система должны предоставить желаемый правильный ответ. Для простоты можно сказать, что система должна правильно сопоставить начальное состояние программы с конечным.

Безопасность собственности

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

Живая собственность

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

Актеры параллельных систем

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

Ресурсы параллельных систем

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

Определенный набор правил

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

Барьеры параллельных систем

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

Обмен данными

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

Ограничение обмена данными

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

Помощь структуры данных

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

Неизменная передача данных

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

Изменяемая передача данных

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

Совместное использование ресурсов ввода / вывода

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

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

import urllib.request

import time

ts = time.time()

req = urllib.request.urlopen('http://www.tutorialspoint.com')

pageHtml = req.read()

te = time.time()

print("Page Fetching Time : {} Seconds".format (te-ts))

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

Выход

Page Fetching Time: 1.0991398811340332 Seconds

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

Что такое параллелизм?

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

параллелизм

Чтобы лучше понять различие между параллелизмом и параллелизмом, рассмотрим следующие моменты:

Параллельно, но не параллельно

Приложение может быть параллельным, но не параллельным, это означает, что оно обрабатывает более одной задачи одновременно, но задачи не разбиты на подзадачи.

Параллельно, но не одновременно

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

Ни параллельно, ни параллельно

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

Параллельно и параллельно

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

Необходимость параллелизма

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

Рассмотрим следующие важные моменты, чтобы понять, почему необходимо достичь параллелизма —

Эффективное выполнение кода

С помощью параллелизма мы можем эффективно выполнять наш код. Это сэкономит наше время, потому что один и тот же код по частям выполняется параллельно.

Быстрее, чем последовательные вычисления

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

Меньше времени выполнения

Параллельная обработка сокращает время выполнения программного кода.

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

Понимание процессоров для реализации

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

Одноядерные процессоры

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

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

Многоядерные процессоры

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

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

Цикл извлечения-декодирования-выполнения

Ядра многоядерных процессоров следуют циклу выполнения. Этот цикл называется циклом Fetch-Decode-Execute . Он включает в себя следующие шаги —

получать

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

раскодировать

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

казнить

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

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