Задача поиска информационных связей при распараллеливании циклов

gence, 24, 603-619.

V.L. Tokarev, D.A Abramov.

METHOD ANOMALY DETECTED

In the articles made review current methods anomaly detected and shows imlementation one method for develop system automatic detection covergence anomaly in continues image stream.

Key words: anomaly, methods anomaly detected, continues image stream, image processing, anomaly detected.

Получено 20.11.12

УДК 004.415.52

А.Н. Ивутин, канд. техн. наук, доц.,

ЗАДАЧА ПОИСКА ИНФОРМАЦИОННЫХ СВЯЗЕЙ ПРИ РАСПАРАЛЛЕЛИВАНИИ ЦИКЛОВ

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

Ключевые слова: параллельные вычисления, циклы, алгоритмы распараллеливания.

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

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

226

получить схему распараллеливания вычислений [2] в последовательной программы.

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

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

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

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

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

Арапбаева [3]. Многие точные методы анализа слабо практикуются в виду высокой вычислительной сложности. Но повышение быстродействия процессоров, на которых производится такой анализ, повышают актуальность точных методов. Тем не менее, «точность» в данном случае относится только к описанному классу пар вхождений, причем без учета контекста.

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

Приведем примеры с такими ситуациями:

1) Наличие внешних переменных в индексных выражениях. Внешние переменные - это переменные, значение которых определяется за пределами исследуемого фрагмента.

2) Наличие в индексных выражениях переменных, которые вычисляются внутри исследуемого фрагмента, но эти значения носят нерегулярный характер.

3) Наличие в индексных выражениях неаффинных зависимостей. Например, счетчик цикла находится в показателе степени или используется косвенная адресация.

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

5) Сложный контекст. Вхождения переменных, между которыми определяется зависимость, находятся в разных функциях.

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

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

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

Рассмотрим следующий цикл:

for

{

A[i+1] = A[i] + C[i]; /* S1*/

B[i+1] = B[i] + A[i+1];} /*S2*/

}

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

Имеются две различных зависимости:

1) S1 использует значение, вычисляемое оператором S1 на более ранней итерации, поскольку итерация i вычисляет A[i+1 ], которое считы-вается в итерации i+1. То же самое справедливо для оператора S2 для B[i] и B[i+1].

2) S2 использует значение A[i+1], вычисляемое оператором S1 в той же самой итерации.

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

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

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

Рассмотрим цикл:

for

{

A[i] = A[i] + B|i|; /* S1 */

B[i+1] = C[i] + D[i]; /* S2 */

}

Оператор S1 использует значение, которое присваивается оператором S2 в предыдущей итерации, так что имеет место зависимость между S2 и S1 между итерациями.

Несмотря на эту зависимость, этот цикл может быть сделан параллельным. Как и в более раннем цикле эта зависимость не циклическая: ни один из операторов не зависит сам от себя и хотя S1 зависит от S2, S2 не зависит от S1. Цикл является параллельным, если только отсутствует циклическая зависимость.

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

1) Зависимость от S1 к S2 отсутствует. Если бы она была, то в зависимостях появился бы цикл и цикл не был бы параллельным. Вследствие отсутствия других зависимостей, перестановка двух операторов не будет влиять на выполнение оператора S2.

2) В первой итерации цикла оператор S1 зависит от значения B[1], вычисляемого перед началом цикла.

Эти два замечания позволяют заменить выше приведенный цикл следующей последовательностью: A[1] = A[1] + B[1];

for

{

B[i+1] = C[i] + D[i];

A[i+1] = A[i+1] + B[i+1];

}

B[101] = C[100] + D[100];

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

Среди методов анализа пространства итераций можно выделить несколько наиболее известных [4, 5]: методы гиперплоскостей, координат, параллелепипедов и пирамид.

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

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

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

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

Рассмотрим небольшой пример:

^Г (1 = 1; I < N i++) ^г 0 = 1; ] < M; ]+ + ) аМ = ар-^] + ар,Л;

Пространство итераций данного фрагмента можно изобразить следующим образом (рис. 1):

Рис. 1. Пространство итераций

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

Немного усложним пример:

^Г

^ъЛ = И1-1^ + ^ьИ^

Пространство итераций данного фрагмента можно изобразить следующим образом (рис. 2):

Рис. 2. Пространство итераций

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

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

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

Приведем один небольшой пример. Допустим, что в программе содержится такой цикл:

for

{

a[i] = a[i] + b[i];

c[i] = c[i-1] + b[i];

}

В данном цикле есть информационные зависимости между срабатываниями второго оператора из тела цикла на i-й и (i-D-й итерациях. Поэтому нельзя просто раздать итерации исходного цикла для выполнения различным процессорам. Однако, достаточно очевидно, что этот цикл

можно разбить на два, первый из которых станет параллельным: for (i = 1; i < N; i++) a[i] = a[i] + b[i]; for (i = 1; i < N; i++) c[i] = c[i-1] + b[i];

В некоторых случаях и эквивалентные преобразования бессильны помочь в распараллеливании программы, но допустимы другие методы при предположении, что можно пренебречь ошибками округления. Например, пусть нужно произвести суммирование элементов массива: for (i = 0, s = 0; i < N; i++) s+=a[i];

Если подойти к этому циклу формально, то распараллелить его не получится, так как между итерациями цикла существуют информационные зависимости. Однако, если ошибками округления, вызванными разным порядком суммирования элементов массива а, допустимо пренебречь, то данный фрагмент можно распараллелить при помощи широко известной схемы сдваивания: на первом шаге первый процессор суммирует элементы а[0] и а[1], второй процессор суммирует элементы а[2] и а[3] и т.д., на следующем шаге попарно суммируются эти частичные суммы и так до получения окончательного результата. Если имеется N/2 процессоров, то весь алгоритм суммирования выполняется за log2N параллельных шагов.

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

Список литературы

1. Ивутин А.Н., Дараган Е.И. Применение сетей Петри и метода построения графа информационных зависимостей для решения задач верификации и распараллеливания вычислений. Известия ТулГУ. Серия: Технические науки. В. 5. Ч. 3. Тула: Изд. ТулГУ, 2011. С. 185-192.

2. Ивутин А.Н., Дараган Е.И. Построение схемы распараллеливания последовательного алгоритма программы, Известия ТулГУ. Серия: Технические науки. Вып. 5. Тула: Изд. ТулГУ, 2012. С. 101-109.

3. Арапбаев Р.Н. Анализ зависимостей по данным: тесты на зависимость и стратегии тестирования // Диссертация на соискание ученой степени кандидата физико-математических наук.

4. Векторизация программ // Векторизация программ: теория, методы, реализация / Сборник переводов статей. М.: Мир, 1991. С. 246-267.

5. Штейнберг Б.Я. Математические методы распараллеливания рекуррентных программных циклов на суперкомпьютеры с параллельной памятью // Ростов-на-Дону, Издательство Ростовского университета, 2004, 192 с.

A.N. Ivutin, E.I. Daragan

The task of multisequencing of cycles in sequential the program is considered. Examples of cycles and application of different algorithms of multisequencing are given.

Key words: parallel computings, cycles, algorithms of multisequencing.

Получено 20.11.12

УДК 621.865

О.А. Игнатова, канд. техн. наук, доц., (4872) 35-02-19 (Россия, Тула, ТулГУ),

Т.А. Акименко, канд. техн. наук, доц., (4872) 23-12-95, tantan72@mail.ru (Россия, Тула, ТулГУ),

Е.С. Игнатова, студент,

ИССЛЕДОВАНИЯ МОБИЛЬНЫХ РОБОТОВ КАК ОБЪЕКТОВ ИЗМЕРЕНИЯ И УПРАВЛЕНИЯ

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

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

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

234