Статья посвящена крайне важному аспекту в работе любой вычислительной системы на сегодняшний день — параллельной работе программ.
Ключевые слова: параллельная работа программ, параллелизм, вычислительная система, процесс, поток, ресурс, процессор
Любая вычислительная система, насколько бы мощной она ни была, обладает ограниченными ресурсами. Оперативная память, устройство чтения и записи информации, процессор — все это и многое другое (речь идет, конечно же, об объектах вычислительной системы) имеет некоторые пределы. Из-за этого возникает острая необходимость использовать эти ресурсы наиболее эффективно, и именно параллельная работа программ является одним из ключевых факторов, позволяющих выполнить поставленную задачу.
Однако прежде чем перейти к тому, как именно осуществляется параллельная работа программ, необходимо разобрать базовые вещи. Таковыми являются понятия процесс и поток. Они довольно похожи, ведь и то, и то является ничем иным, как определенной последовательностью команд некоторой программы. Но, тем не менее, они имеют существенные различия. Так, процессы изолированы друг от друга, они используют разные адресные пространства и не могут получить доступа к переменным и структурам других процессов. В свою очередь, потоки выполняются в рамках некоторого процесса, используют одно адресное пространство и спокойно взаимодействуют между собой, при этом никоим образом не мешая работе друг друга. Именно благодаря потокам можно заметно повысить скорость выполнения некоторого приложения, просто разбив его на несколько последовательных потоков.
Также необходимо отметить, что ресурсы вычислительной системы, о которых говорилось в начале статьи, подразделяются на несколько категорий в зависимости от того, как именно они используются, а именно на [1]:
- Выделяемые ресурсы — это ресурсы, которые выделяются некоторому процессу и монопольно им используются.
- Повторно распределяемые ресурсы — это ресурсы, которые могут как выделяться, так и высвобождаться прямо во время выполнения процессов.
- Разделяемые ресурсы — это ресурсы, которые постоянно находятся в общем использовании и выделяются процессам в режиме разделения времени.
- Многократно используемые ресурсы — это ресурсы, которые могут одновременно использоваться несколькими процессами.
Конечно, использование потоков может заметно повысить производительность вычислительный системы, ведь тогда ее ресурсы будут использоваться куда более правильно и рационально. Однако все это ведет к серьезному повышению сложности программирования подобных параллельных программ, в отличие от последовательных. Происходит это по нескольким причинам:
- Выполнение командных последовательностей различных потоков может чередоваться во время их исполнения, причем время между выполнением команд различных потоков может также изменяться.
- При различных запусках программы возможны различные последовательности выполнения команд различных потоков.
- Результат выполнения программы должен быть правильным вне зависимости от того, сколько времени прошло между выполнением команд различных потоков. Необходимо исключить зависимость результатов выполнения от того путем анализа взаимовлияния потоков и разработки методов их исключения [1].
Одна из проблем, которую необходимо решить для обеспечения правильной работы параллельной программы, заключается в общем использовании разделяемых ресурсов, таких, как данные, файлы, устройства и многое другое. Чтобы разрешить данную проблему, необходимо реализовать следующие функции [1]:
- Возможность определения доступности запрашиваемых ресурсов.
- Возможность выделения свободного ресурса одному из потоков, запросившему его.
- Возможность блокировки потоков, которые пытаются получить доступ к уже занятым другими потоками ресурсам.
Из всего вышеперечисленного можно сделать вывод, что один ресурс может использоваться только одним потоком с момента занятия потоком и до момента освобождения. Данный механизм называется взаимоисключением потоков. Помимо его выполнения также необходимо достичь выполнения следующих правил [1]:
- Отсутствие взаимной блокировки одного потока другим.
- Эффективный выбор потока, который следующим начнет работу с ресурсом, то есть выбор нужного потока за наименьшее возможное время.
- Исключение ситуаций, когда время ожидания освобождения ресурса одним потоком приближается к бесконечности.
Крайне важно проводить определенные мероприятия для повышения эффективности параллельных программ. Основных их четыре [1]:
- Оптимизация количества потоков. Избыточное количество потоков негативно сказывается на работе вычислительных устройств, перестает продуктивно использоваться кэш-память, становится очень сложной организация синхронизации и взаимоисключения потоков. Поэтому необходимо очень осторожно выбирать число одновременно работающих потоков.
- Минимизация взаимодействия потоков. Чем сильнее потоки независимы друг от друга, тем меньше времени тратится на задержки, когда один поток для продолжения своей работы ждет завершения выполнения других потоков. Для выполнения данной задачи нужно стремится уменьшить число взаимодействий между потоков, повышать эффективность работы алгоритмов распределения ресурсов между потоками, обеспечения более быстрого выполнения потоков за счет исключения ситуация, когда работа одного потока прерывается другим, чье выполнение является намного более приоритетным в данный момент времени.
- Оптимизация работы с памятью. Эффективная работа с памятью является проблемой всех программ, но для параллельных она приобретает особое значение. Самый лучший вариант — это достижение такого состояния, когда работа ведется исключительно с кэш-памятью без обращения к более медленной оперативной памятью. Тем не менее, при использовании общей памяти и нескольких устройств кэш-памяти возникают дополнительные проблемы, требующие решения:
– Обеспечение однозначности кэш-памяти. Проблема может возникнуть, когда одна и та же переменная находится одновременно в двух запоминающих устройствах, в одном из которых она подвергается изменению.
– Уменьшение миграции потоков между ядрами и процессорами. Крайне важно сохранить работу потока на одном вычислительном элементе, так как только тогда для него не изменится его запоминающий элемент.
– Устранение эффекта ложного разделения данных. Данная проблема возникает тогда, когда некоторые тесно связанные между собой данные делятся между разными устройствами кэш-памяти, причем изменение, касающиеся одной части данных затрагивает и другую часть, но ее размещение в другом устройстве кэш-памяти серьезно затрудняет и тормозит работу.
- Использование потоко-ориентированных библиотек. Потоко-ориентированные библиотеки — это библиотеки, специально разработанные для параллельной работы вычислительных систем с общей памятью. Иногда их использование является обязательным условием.
Таким образом, использование параллелизма в работе программ заметно повышает эффективность любой вычислительной системы, поэтому их использование не просто возможно, а жизненно необходимо и крайне выгодно.
Литература:
- Гергель, В. П. Высокопроизводительные вычисления для многопроцессорных многоядреных систем: Учебник. / В. П. Гергель. — М.: Издательство Московского университета, 2010. — 544 с., илл.