Санкт-Петербургский государственный университет
Опубликован: 11.02.2010 | Доступ: свободный | Студентов: 531 / 93 | Оценка: 4.41 / 4.44 | Длительность: 08:19:00
Специальности: Программист
Лекция 1:

Введение

Лекция 1: 1234 || Лекция 2 >

Планирование вычислений

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

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

Хозяин/работник (Master/slave)

Главная задача отвечает за размещение подчиненных задач (рис. 1.10). Подчиненная задача получает исходные данные для обработки от главной задачи и возвращает ей результат работы.

Простая схема хозяин/работник

увеличить изображение
Рис. 1.10. Простая схема хозяин/работник

Иерархическая схема хозяин/работник

Подчиненные задачи разделены на непересекающиеся подмножества и у каждого из этих подмножеств есть своя главная задача (рис. 1.11). Главные задачи подмножеств управляются одной "самой главной" задачей.

Иерархическая схема хозяин/работник

увеличить изображение
Рис. 1.11. Иерархическая схема хозяин/работник

Децентрализованные схемы

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

Динамически сбалансированная загрузка может быть эффективно реализована, если учтены следующие соображения:

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

увеличить изображение
Рис. 1.12. Децентрализованная схема

Многопоточные программы

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

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

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

  • гонки за данными;
  • блокировки;
  • активные блокировки;
  • несбалансированность загрузки.

Гонки за данными

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

  1. конфликт "чтение-запись";
  2. конфликт "запись-запись".

Имеются два способа борьбы с гонками за данными:

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

Гонки за данными могут быть скрыты синтаксисом языка программирования. Некоторые примеры приведены в табл. 1.1

Таблица 1.1. Примеры конструкций языка программирования, в которых могут возникать гонки за данными
Поток 1 Поток 2 Причина возникновения гонок за данными
X += 1 X += 2 Компилятор заменяет операцию += раздельными операциями чтения и записи X
A[i] += 1 A[j] += 2 Возможно совпадение значений индексов i и j
*p  +=  1 *q += 2 Указатели p и q могут ссылаться на один адрес
Func(1) Func(2) Func может суммировать значение аргумента и значение внутренней разделяемой переменной
Add [abc],   1 add [abc],   2 На уровне команд модификация [ abc ] заменяется раздельными операциями чтения и записи

Блокировки

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

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

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

Лекция 1: 1234 || Лекция 2 >