Предисловие В этот том сборника “Труды Института Системного Программирования" вошли статьи, отражающие ряд направлений исследований и разработок, выполняемых в Институте системного программирования Российской академии наук. Цикл из первых трех работ сборника отражает новые решения в области создания средств разработки параллельных программ в модели "параллелизма по данным" (SPMD). В первой статье рассматривается возможность создания параллельных программ средствами моделей параллелизма высокого уровня, отражающих специфику прикладной задачи и учитывающих особенности архитектуры используемой вычислительной системы. Во второй и третьей статьях цикла дается описание разработанной авторами среды ParJava, являющейся расширением среды Java средствами разработки масштабируемых, переносимых, объектно-ориентированных параллельных программ для однородных и неоднородных вычислительных систем с распределенной памятью. Вопросы оптимизации преобразований при реализации редуктивных операций над массивами данных рассматриваются в статье "Применимость тайлинга для компиляции редукций в языке С[]". Следующие две работы посвящены актуальной проблеме взаимодействия объектно-ориентированных программ с реляционными базами данных. Работа “Обеспечение совместимости протоколов Ipv4 и Ipv6: бесконтекстный IP/ICMP транслятор в среде Linux” предоставляет одно из решений задачи перехода на протокол следующего поколения Ipv6 для компьютерных сетей. В работе “Возможности использования технологии детерминированного хаоса в системах автономного адаптивного управления” осуществлена попытка слияния разрабатываемого авторами метода построения систем автономного адаптивного управления и использования детерминированного хаоса для запоминания больших массивов упорядоченной информации с ассоциативным способом обращения к ней. В работе “Применение геоинформационных технологий к автоматизированному проектированию систем радиосвязи” рассмотрены подходы к построению специализированной геоинформационной базы данных, используемой при разработке систем планирования радиосвязи. Член-корреспондент РАН В.П.Иванников 4
Объектные модели высокого уровня для разработки эффективных программ с параллелизмом по данным∗ О.И. Самоваров, С.С. Гайсарян, В.В. Бабкова Аннотация. В данной статье рассматривается возможность создания параллельных программ средствами моделей параллелизма высокого уровня, которые отражают специфику прикладной задачи и учитывают особенности архитектуры конкретного вычислительного комплекса. Такие модели призваны скрыть от разработчика уровень MPI (Message Passing Interface) – среды передачи сообщений [1]. Использование объектных моделей параллелизма превращает процесс разработки параллельных программ заданной прикладной области в отработанную технологию. Это позволяет значительно сократить время, затрачиваемое на создание и отладку параллельных программ.
1. Введение С более глубоким проникновением информационных технологий в жизнь человека увеличивается круг задач, для решения которых требуются значительные вычислительные ресурсы. Если раньше это были задачи, связанные с научно-техническими расчетами, то теперь вычислительные мощности, сопоставимые с суперкомпьютерными, требуются в самых разных областях человеческой деятельности. Например, моделирование графических трехмерных сцен в процессе дизайна самой разной направленности, организация оперативного поиска информации в хранилищах баз данных, обработка массированных запросов в компаниях, предоставляющих коммуникационные услуги. В настоящее время, как альтернатива суперкомпьютерам появились и завоевывают все большую популярность вычислительные кластеры. Кластер – это система параллельной или распределенной обработки, которая состоит из узлов – отдельных компьютеров, соединенных между собой быстрой локальной сетью, например, Myrinet [2] и работающих совместно как один интегрированный вычислительный ресурс [3]. Узлом кластера может быть ∗
одно- или многопроцессорный компьютер, имеющий память, устройство ввода-вывода и операционную систему. Конструктивно узлы кластера могут быть собраны в общем корпусе или разнесены в пространстве. Такие кластеры легко обслуживать, расширять и модернизировать. Они мобильны и относительно недороги, а их мощность сопоставима с суперкомпьютерной. Суммируя сказанное, можно сделать вывод о том, что вопросы создания простых и эффективных средств разработки параллельных программ сегодня как никогда актуальны, что подтверждается и многочисленными исследованиями в этой области, результаты которых публикуются в научной периодике и на сайтах в Интернет [4]. Одним из таких средств является среда ParJava [5]. Среда ParJava расширяет среду Java [6] средствами разработки программ с параллелизмом по данным, как для однородных, так и для неоднородных параллельных вычислительных систем с распределенной памятью. Программы для многопроцессорных вычислительных комплексов с распределенной памятью (суперкомпьютеров, кластеров, локальных сетей), как правило, создаются на языках C, C++ и Fortran, расширенных средствами, реализующими обмен сообщениями. В настоящее время наиболее широкое распространение получили два стандартных интерфейса, описывающих межпроцессорные взаимодействия, – MPI (Message Passing Interface) и PVM (Parallel Virtual Machine) [7]. Эти интерфейсы реализованы как библиотеки к языкам C, C++, Fortran почти для всех существующих параллельных платформ. Наибольшей популярностью у разработчиков пользуются реализации интерфейса MPI. Параллельная программа, использующая MPI, может рассматриваться как система взаимодействующих процессов, каждый из которых выполняется на своем процессоре. От разработчика такой программы требуется распределить данные и вычисления, организовать межпроцессорные взаимодействия средствами обмена сообщений. Эффективность и масштабируемость параллельных MPI программ в большой степени может зависеть от архитектуры вычислительного комплекса, на котором она выполняется. И в некоторых случаях вместо ускорения выполнения программы можно получить обратный эффект. Поэтому процесс проектирования, реализации и отладки параллельной программы для некоторого вычислительного комплекса с распределенной памятью включает в себя не только разработку синтаксически и семантически корректного кода, но также и отладку эффективности его выполнения на этом вычислительном комплексе. Кроме того, отладка MPI программы затруднена еще и тем, что ее поведение в процессе выполнения недетерминировано. Несмотря на разнообразие функциональностей, MPI не предоставляет средств, необходимых для решения описанных выше задач, что делает разработку параллельных MPI программ трудоемким процессом.
Работа поддерживалась грантом РФФИ 99-01-00206
5
6
В данной статье рассматривается возможность иного подхода к созданию параллельных программ. Этот подход основан на использовании моделей параллелизма, которые отражают специфику прикладной задачи и учитывают особенности архитектуры конкретного вычислительного комплекса. Такие модели призваны скрыть от разработчика уровень MPI -среды передачи сообщений, предоставив средства распараллеливания более высокого уровня [8]. Конечно, такой подход ограничивает круг решаемых задач в рамках одной модели, однако превращает процесс создания параллельных программ заданной прикладной области в отработанную технологию. Это позволяет значительно сократить время, затрачиваемое на разработку и отладку параллельных программ. В качестве средства разработки моделей параллелизма рассматривается язык программирования Java. Таким образом, разрабатываемые модели будут обладать всеми преимуществами объектно-ориентированной технологии, а значит простыми в создании, модификации и отладке. Переносимость Java программ позволит использовать объектные модели параллелизма на разных вычислительных платформах. Кроме того, рассматриваемые объектные модели высокого уровня разрабатываются как часть среды ParJava. Далее мы коротко рассмотрим возможности и состав объектной модели JavaDVM [8]. Также разберем два примера параллельных программ. Первая параллельная программа разработана с использованием объектной модели параллелизма Java-DVM, вторая - средствами языка Java, расширенного библиотекой MPI. Обе программы решают уравнение Лапласа методом Якоби и реализованы в рамках модели SPMD (Single Program Multiple Data) [3]. В заключении мы проведем сравнительный анализ этих примеров, что позволит нам яснее увидеть достоинства и недостатки использования объектных моделей параллелизма при разработке параллельных программ.
2. Объектная модель Java-DVM Объектная модель Java-DVM представляет собой пакет Java классов, которые реализуют модель параллелизма DVM. Модель DVM была разработана в Институте прикладной математики им. М.В. Келдыша РАН [10]. Она предназначена для создания переносимых и эффективных вычислительных параллельных приложений. Аббревиатура DVM соответствует двум понятиям: Distributed Virtual Memory и Distributed Virtual Machine. Первое отражает наличие единого адресного пространства. Второе отражает использование виртуальных машин для двухступенчатой схемы отображения данных и вычислений на реальную параллельную машину.
7
В рамках модели разработчику предоставляются следующие возможности параллельного выполнения программы: выделение сети виртуальных процессоров, на которых будет выполняться параллельная программа. В дальнейшем эта сеть будет отображена на процессоры реального вычислительного комплекса; распределение данных; распределение вычислений; спецификация параллельно выполняющихся секций (параллельных задач) и отображение их на процессоры;
программы
организация эффективного доступа к удаленным (расположенным на других процессорах) данным; организация эффективного выполнения редукционных операций – глобальных операций с расположенными на различных процессорах данными, число которых уменьшается после выполнения (таких, как их суммирование или нахождение их максимального или минимального значения). Кроме этого пользователю предлагаются средства отладки и анализа параллельной программы, о которых будет сказано ниже. В рамках модели DVM предполагается, что параллельная программа разрабатывается для многопроцессорной системы с распределенной памятью, которую программист может представлять в виде 2-х архитектур – линейка или прямоугольная многомерная решетка процессоров. Это позволяет разработчику компактно и наглядно описывать распределение данных и вычислений. В объектной модели Java-DVM такое представление вычислительной среды описывается соответствующим классом пакета java.dvm – VPM (название класса от Virtual Parallel Machine). Создав экземпляр подобного класса, и изменяя его атрибуты, разработчик может управлять выделением сети виртуальных процессоров требуемой архитектуры, на которых будет выполняться его параллельная программа. В процессе запуска программы виртуальная сеть процессоров будет отображена на реальный вычислительный комплекс. При этом пользователю дается механизм управления этим отображением. Распределение данных осуществляется разделением какого-либо из измерений определенного массива на примерно равные части и размещением этих частей на процессоры. Для примера на рисунке 1 показано y-распределение массива (вдоль столбцов) на линейку процессоров n1 – n4.
8
import java.dvm.*; public class MyClass { public static void main (String[] args) { /* Выделяется сеть виртуальных процессоров. Сеть рассматривается как линейка процессоров. */ VPM vpm = new VPM();
Рис. 1. Y-распределение массива на линейку процессоров. Как было сказано выше, многопроцессорная вычислительная система, на которой будет выполняться параллельная программа, может рассматриваться не только как линейка процессоров, но и как многомерная решетка. Например, представим, что вычислительная система состоит из N процессоров. Тогда в рамках модели DVM она может быть представлена как 2-мерная матрица процессоров размерностью N1 на N2 (N=N1*N2). В этом случае одно из измерений массива может быть разделено на N1 отрезков, а какое-либо другое на N2 число отрезков – 2d-распределение. В результате массив будет разделен на N1*N2 частей, каждая из которых будет размещена на соответствующий процессор 2-мерной решетки. На рис. 2 показано распределение массива на 2мерную решетку процессоров размерностью 2x2.
/* Массив da размерностью 100x100 распределен на процессоры виртуальной сети vpm. Используется y-распределение */ DoubleDArray da = new DoubleDArray(new RowDistribution(vpm, 100, 100)); } }
Рис. 3. Пример реализации распределенного массива средствами библиотеки Java-DVM Распределение вычислений определяется распределением данных. Разработчик параллельной программы может создать в своей программе параллельные циклы и указать для каждого из них «базовый» массив. Базовым массивом называется массив, определяющий индексное пространство, по которому будет совершаться обход в параллельном цикле. В этом случае витки этих циклов будут выполняться на тех процессорах, на которых размещены соответствующие элементы их базовых массивов. Предложения программы, расположенные вне параллельных циклов, выполняются на всех процессорах и, следовательно, вычисляют значения только размноженных переменных.
Рис. 2. 2d-распределение массива на двумерную решетку процессоров. В определениях модели DVM распределяются только массивы, все остальные данные размещаются на процессорах целиком и называются размноженными. В Java-DVM предлагаются классы, описывающие x-, y- и 2d способы распределения массивов – ColumnDistribution, RowDistribution и 2dDistribution соответственно. Определив способ распределения, разработчик может создать распределенный массив требуемого типа данных. Классы ряда xxxDArray описывают распределенные массивы для всех простых типов данных в языке Java. На рис. 3 показан пример создания распределенного массива в нотациях объектной модели Java-DVM.
9
Рис. 4. Распределение витков параллельного цикла на линейку процессоров.
10
На рис. 4 показано распределение витков параллельного цикла на линейку процессоров n1-n4 совместно с матрицей А размерностью 40x20. Для реализации параллельных циклов в Java-DVM есть классы блока xxxDForall. Это абстрактные классы, которые описывают параллельную обработку распределенных массивов для всех простых типов данных в языке Java. Разработчик должен создать свой собственный класс, расширяющий один из классов блока xxxDForall, в котором ему необходимо реализовать абстрактный метод body(). Этим методом описывается правило обхода элементов распределенного массива. На рис. 5 приведен пример, в котором показано, как реализуются параллельные циклы в Java-DVM. import java.dvm.*; public class MyClass { public static void main (String[] args) { /* Выделяется сеть виртуальных процессоров. Сеть рассматривается как линейка процессоров. */ VPM vpm = new VPM(); /* Массив da размерностью 100x100 распределен на процессоры виртуальной сети vpm. Используется y-распределение */ DoubleDArray da = new DoubleDArray(new RowDistribution(vpm, 100, 100)); /* Параллельный цикл с базовым распределенным массивом da */ UserDCycle dc = new UserDCycle(da);
{
}
/* Записать в элемент (i,j) базового массива a значение суммы индексов i+j */ a.putElem(i, j, i+j);
}
Рис. 5. Пример реализации параллельного цикла средствами библиотеки Java-DVM. Перед выполнением программы необходимо, чтобы все данные, которые требуются для вычислений, находились в локальной памяти узла. В случае параллельных циклов это условие выполняется редко. Очень часто случается ситуация, когда одна и та же ссылка на элемент массива в разных витках параллельного цикла вызывает обращение, как к локальным, так и нелокальным элементам массива. В DVM доступ к удаленным данным осуществляется путем их буферизации в памяти узлов вычислительной системы и обменом буферов сразу для нескольких витков цикла одновременно. Импортируемые элементы, которые примыкают к локальным (по их индикации в массиве) элементам, образуют так называемые грани. Грани имеют ширину. Например, предположим, что выделенная виртуальная сеть представляет собой линейку процессоров n1-n3 (рис. 6).
/* Выполнить параллельный цикл */ dc.execute(); } } import java.dvm.*; // Класс пользователя, в котором реализуется абстрактный метод //body() class UserDCycle extends DoubleDForall { DoubleDArray da; /* Базовый массив */ public ACycleDJacobi(DoubleDArray a) { super(a); this.a = a; } /* Метод, в котором определяется порядок обхода элементов базового массива */ public void body(int i, int j)
11
Рис. 6. Грани импортируемых данных и теневые грани. Тогда грани импортируемых элементов располагаются на соседних процессорах, слева и справа. Увеличим память локальных секций распределенного массива на ширину граней импортируемых данных. Эта дополнительная память в модели DVM называется теневыми гранями секции
12
/* Решение уравнения Лапласа методом Якоби. Программа разработана в рамках объектной модели параллелизма Java-DVM */ import java.dvm.*; public class DJacobi { // Определить количество итераций static final int MAXIT = 10;
массива. Перед выполнением параллельного цикла грани импортируемых данных пересылаются на соседние процессоры и копируются в соответствующие теневые грани. Таким образом, осуществляется локализация удаленных данных. Выделение теневых граней, пересылка граней импортируемых данных, а также замена обращений к удаленным данным на обращения к их копиям в теневых гранях - все это осуществляется экземплярами классов реализующих распределенные массивы, т.е. блоком классов xxxDArray. Модель DVM предоставляет разработчику средства отладки и анализа параллельных программ. Отладка параллельной DVM программы проходит в несколько этапов. На первом этапе программа отлаживается как последовательная. На втором этапе программа выполняется как параллельная в специальном режиме. В этом режиме промежуточные результаты параллельного выполнения сравниваются с эталонными результатами последовательного выполнения. Для осуществления этих этапов DVM предоставляет специальный инструмент – динамический отладчик. Средства анализа производительности базируются на накоплении в памяти трассировки с временами выполнения определенных конструкций параллельной программы. Пользователь может получить информацию о некоторых характеристиках программы (или ее частей), позволяющих ему сделать заключения об эффективности ее выполнения. Важно отметить, что разработчику предоставляются средства отладки в терминах самой модели.
public static void main (String[] args) { // Получить размер матрицы //(Матрица квадратная размерностью ln x ln). int ln = Integer.valueOf(args[0]).intValue(); /* Выделяется сеть виртуальных процессоров. Сеть рассматривается как линейка процессоров. */ VPM vpm = new VPM(); /* Массив da размерностью ln x ln распределен на процессоры виртуальной сети vpm. Используется y-распределение */ DoubleDArray da = new DoubleDArray(new RowDistribution(vpm, ln, ln)); /* Массив db размерностью ln x ln распределен на процессоры виртуальной сети vpm. Используется y-распределение */ DoubleDArray db = new DoubleDArray(new RowDistribution(vpm, ln, ln));
3. Сравнение Java-DVM и Java+MPI Теперь, когда мы познакомились с возможностями объектной модели параллелизма Java-DVM, рассмотрим два примера параллельной программы. Обе программы разработаны в рамках модели параллелизма по данным (SPMD) и решают уравнение Лапласа методом Якоби. Первая программа реализована средствами Java-DVM, вторая средствами языка Java расширенного библиотекой MPI. Java-DVM. Параллельная программа представлена тремя классами: DJacobi, DCycleA, DcycleB, InitDArray. Класс DJacobi (рис. 7) реализует основную логику программы и содержит единственный метод. main().
/* Инициализация распределенного массива в параллельном цикле */ InitDArray ini = new InitDArray(db); /* Выполнить параллельный цикл инициализации */ ini.execute(); /* Определить параллельный цикл с базовым массивом ас */ DCycleA ac = new DCycleA(da, db, 0, 0, da.getWidth(), da.getHeight(), 1, 1); /* Определить параллельный цикл с базовым массивом bc */ DCycleB bc = new DCycleB(da, db, 1, 1, da.getWidth()-2, da.getHeight()-2, 1, 1); /* Итерационный цикл */ for(int i=0; i<MAXIT; i++) {
13
14
/* Выполнить паралельный цикл ac */ ac.execute(); /* Выполнить паралельный цикл bc */ bc.execute(); }
Создаются два параллельных цикла с базовым массивом da. Индексное пространство определяется входными параметрами конструктора классов DcycleA и DcycleB, а именно: 0, 0, da.getWidth(), da.getHeight() и 1, 1, da.getWidth()-2, da.getHeight()2 соответственно. Методы getWidth(), getHeight() объекта da возвращают размер распределенной части массива. Фактически это означает, что параллельный цикл на каждом процессоре обработает только «свою» часть индексного пространства.
} }
Рис. 7. Решение уравнение Лапласа методом Якоби. Классы DJacobi, DcycleA, InitDArray реализуют параллельные циклы. Рассмотрим класс Djacobi подробнее. При решении задачи предполагается, что матрицы квадратные и имеют одинаковые размерности. Размер матриц определяется переменной ln, которой присваивается значение входного параметра.
DCycleA ac = new DCycleA(da, db, 0, 0, da.getWidth(), da.getHeight(), 1, 1); DCycleB bc = new DCycleB(da, db, 1, 1, da.getWidth()-2, da.getHeight()-2, 1, 1); Далее в программе определяется итерационный цикл, в котором параллельные циклы выполняются MAXIT число раз. for(int i=0; i<MAXIT; i++) { ac.execute(); bc.execute(); }
int ln = Integer.valueOf(args[0]).intValue(); Следующее предложение программы создает объект, определяющий архитектуру сети виртуальных процессоров. Дальнее распределение данных и вычислений будет осуществляться именно на нее. В данном случае виртуальная сеть представляется как линейка процессоров. VPM vpm = new VPM(); Далее создаются два распределенных массива. Эти массивы будут распределены методом y-распределения (вдоль столбцов массива) на виртуальную сеть процессоров vpm. DoubleDArray da = new DoubleDArray(new RowDistribution(vpm, ln, ln)); DoubleDArray db = new DoubleDArray(new RowDistribution(vpm, ln, ln));
Теперь рассмотрим классы, описывающие параллельные циклы (рис. 8, 9, 10). Класс InitDArray описывает параллельный цикл инициализации распределенного массива. Класс DCycleA описывает параллельный цикл, в котором переопределяются значения элементов массива a значениями элементов массива b. Класс DCycleB описывает параллельный цикл, в котором в соответствии с семантикой задачи вычисляются значения элементов массива b. /* / Параллельный цикл инициализации распределенного массива */ import java.dvm.*; /* Пользовательский класс, описывающий параллельные циклы, должен наследоваться от классов блока xxxDForall и реализовать абстрактный метод body() */ class InitDArray extends DoubleDForall { DoubleDArray a;
Этим предложением программы создается параллельный цикл инициализации распределенного массива. После того как цикл создан, его можно выполнить методом execute(). Вспомним, что InitDArray пользовательский класс, в котором реализуется абстрактный метод body() класса DoubleDForall. Именно в этом методе определяется предложение, обрабатывающее элементы массива. В данном случае элементы массива инициализируются предложением a.putElem(i, j, 1.0 + i + j). Подробнее об этом будет сказано ниже при рассмотрении классов, описывающих параллельные циклы.
/* Конструктор класса. Массив, полученный как параметр, определяется базовым */ public InitDArray(DoubleDArray a) { super(a); this.a = a;
InitDArray ini = new InitDArray(db); ini.execute();
15
16
}
/* Реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется предложение, обрабатывающее элементы распределенного массива */ public void body(int i, int j) { a.putElem(i, j, b.getElem(i, j)); }
/* Реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется предложение, обрабатывающее элементы распределенного массива */ public void body(int i, int j) { a.putElem(i, j, 1.0 + i + j); }
}
Рис. 9. Параллельный цикл переопределения значений элементов массивов.
}
Рис. 8. Параллельный цикл инициализации распределенного массива. В классе InitDArray реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется выражение, обрабатывающее распределенный массив. В данном случае это инициализация элементов распределенного массива а значениями выражения a.putElem(i, j, 1.0 + i + j).
В классе DCycleA реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется выражение, обрабатывающее распределенный массив. В данном случае в параллельном цикле переопределяются значения элементов массива a значениями элементов массива b. public void body(int i, int j) { a.putElem(i, j, b.getElem(i, j)); }
public void body(int i, int j) { a.putElem(i, j, 1.0 + i + j); }
/* / Класс DCycleB описывает параллельный цикл, в котором в / соответствии с семантикой задачи вычисляются значения элементов массива b. */ import java.dvm.*;
/* / Класс DCycleA описывает параллельный цикл, в котором / переопределяются значения элементов массива а значениями / элементов массива b */ import java.dvm.*;
/* Пользовательский класс, описывающий параллельные циклы, должен наследоваться от классов блока xxxDForall и реализовать абстрактный метод body() */ class DCycleB extends DoubleDForall { DoubleDArray a, b;
/* Пользовательский класс, описывающий параллельные циклы, должен наследоваться от классов блока xxxDForall и реализовать абстрактный метод body() */ class DCycleAi extends DoubleDForall { DoubleDArray a, b;
/* Конструктор класса. Массив a, полученный как параметр, определяется базовым */ public BCycleDJacobi(DoubleDArray a, DoubleDArray b, int startx, int starty, int endx, int endy, int stepx, int stepy) { super(b, startx, starty, endx, endy, stepx, stepy); this.a = a; this.b = b; }
/* Конструктор класса. Массив a, полученный как параметр, определяется базовым */ public ACycleDJacobi (DoubleDArray a, DoubleDArray b, int startx, int starty, int endx, int endy, int stepx, int stepy) { super(a, startx, starty, endx, endy, stepx, stepy); this.a = a; this.b = b; }
17
18
/* Реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется предложение, обрабатывающее элементы распределенного массива */ public void body(int i, int j) { b.putElem(i, j, 0.25* (a.getElem(i-1, j)+a.getElem(i+1, j)+ a.getElem(i, j-1)+a.getElem(i, j+1))); } }
параметр, поскольку дальнейшее поведение программы зависит именно от него. /* / Решение уравнения Лапласа методом Якоби. Программа разработана средствами языка Java, расширенного библиотекой MPI */ import java.util.*; import mpi.*; class DJacobi { // Определить количество итераций static final int MAXIT = 10;
Рис. 10. Параллельный цикл, вычисляющий значения элементов массива. В классе DCycleB реализуется абстрактный метод родительского класса DoubleDForall. В этом методе определяется выражение, обрабатывающее распределенный массив. В данном случае в параллельном цикле в соответствии с семантикой задачи вычисляются значения элементов массива b. public void body(int i, int j) { b.putElem(i, j, 0.25* (a.getElem(i-1, j)+a.getElem(i+1, j)+a.getElem(i, j-1)+a.getElem(i, j+1))); } Java + MPI. Рассмотрим теперь программу, решающую ту же задачу, но написанную на языке Java, расширенного библиотекой MPI. Класс Jacobi содержит единственный метод main(), в котором и реализована вся логика программы. Для большей наглядности разобьем программу на несколько блоков: инициализация (рис. 11);
// Массив static float A[][] = new float[ln][ln]; // Размер рассылаемой части массива для каждого узла int each; /* Метод main */ public static void main(String args[]) { // Получить размер матрицы. (Матрица квадратная размерностью ln x ln). static int ln = Integer.valueOf(args[0]).intValue(); // Буфер, необходимый для рассылки частей процессоры static float Ahelp[] = new float[ln*(ln - 1)]; try { // Инициализация MPI MPI.Init(args);
подготовка массива к распределению (рис. 12); распределение массива (рис. 13);
массива
на
// Номер текущего узла int myrank = MPI.COMM_WORLD.Rank();
локализация удаленных данных (рис. 14); итерационный цикл (рис. 15);
// Размер сети int size = MPI.COMM_WORLD.Size();
завершение программы (рис. 16).
Рис. 11. Инициализация.
Рассмотрим каждый из них подробно. Инициализация: В первых строках декларируются необходимые переменные. В качестве входного параметра ln программа получает значение размерности массива. Далее в этой части программы инициализируется библиотека MPI и определяются параметры виртуальной сети. Переменная myrank определяет текущий номер узла, на котором выполняется код программы. Это важный
19
Подготовка массива к распределению: В этом блоке происходит инициализация массива на нулевом узле. Прежде чем распределить двумерный массив, его надо представить в виде строки. У интерфейса MPI есть ограничение – методами MPI простые типы данных можно пересылать только
20
// Разослать части маcсива по узлам виртуальной сети MPI.COMM_WORLD.Scatterv(Ahelp, 0 , scounts, disps, MPI.FLOAT, Alocalhelp, 0, ln*each, MPI.FLOAT, 0); MPI.COMM_WORLD.Barrier();
одномерными массивами. Далее вычисляются размеры рассылаемых частей массива и их смещение в буфере пересылки. // Инициализация массива A if(myrank == 0) { for(int j = 0; j < ln; j++) for(int i = 0; i < ln; i++) A[i][j] = (float)(1.0 + i + j); int p = 0; // Подготовить буффер рассылки for(int j = 1; j < ln - 1; j++) for(int i = 0; i < ln; i++) { Ahelp[p] = A[i][j]; p++; } }
// Подготовить локальные массивы для вычислений int l = 0; for(int j = 1; j < each + 1; j++) for(int i = 0; i < ln; i++) { Alocal[i][j] = Alocalhelp[l]; l++; }
Рис. 13. Распределение массив. Локализация удаленных данных: Перед началом вычислений требуется локализовать удаленные данные. Для этого выделяется память под грани импортируемых данных SMas и теневые грани RMas. После этого каждый узел рассылает своим соседям импортируемые грани данных.
// Размеры частей рассылаемого массива int scounts[] = new int[size]; // Смешения этих частей в буфере рассылки int disps[] = new int[size];
// Грани импортируемых данных float[] SMas = new float [ln];
// Вычиление размеров частей массива, которые будут рассылаться по процессорам for(int i = 0; i < size; ++i) { scounts[i] = (int)Math.floor((float)ln / (float)size); if ( i < (ln - size*scounts[i])) scounts[i]++; each = scounts[myrank]; scounts[i] *= ln; for(int j = 0; j < i; j++) disps[i] += scounts[j]; }
// Теневые грани float[] RMas = new float [ln]; // Разослать грани импортируемых данных и скопировать их // теневые грани на левом узле if(myrank == 0) { for(int i = 0; i < ln; i++) Alocal[i][0] = A[i][0]; for(int i = 0; i < ln; i++) SMas[i] = A[i][ln - 1]; MPI.COMM_WORLD.Send(SMas, 0, ln, MPI.FLOAT, size 200); } // Разослать грани импортируемых данных и скопировать их // теневые грани на правом узле if(myrank == size - 1) { MPI.COMM_WORLD.Recv(RMas, 0, ln, MPI.FLOAT, 0, 200); for(int i = 0; i < ln; i++ ) Alocal[i][each + 1] = RMas[i]; } // Разослать грани импортируемых данных и скопировать их
Рис. 12. Подготовка массива к распределению.
Распределение массива: Массив распределяется равномерно по узлам сети методом y-распределения, - массив «режется» вдоль оси у. Выделяется память под локальные части массива на каждом процессоре. Далее части массива рассылаются методом Scatterv() по узлам виртуальной сети. // Массивы, требующиеся для вычислений float Blocal[][] = new float[ln][each]; float Alocalhelp[] = new float[ln*each];
21
22
в
1, в
в
// теневые грани на всех других узлах if(myrank > 0) { for(int i = 0; i < ln; i++) SMas[i] = Alocal[i][1]; MPI.COMM_WORLD.Send(SMas, 0, ln, MPI.FLOAT, 200); MPI.COMM_WORLD.Recv(RMas, 0, ln, MPI.FLOAT, 200); for(int i = 0; i < ln; i++ ) Alocal[i][0] = RMas[i]; } if(myrank < size - 1) { for(int i = 0; i < ln; i++) SMas[i] = Alocal[i][each]; MPI.COMM_WORLD.Send(SMas, 0, ln, MPI.FLOAT, 200); MPI.COMM_WORLD.Recv(RMas, 0, ln, MPI.FLOAT, 200); for(int i = 0; i < ln; i++ ) Alocal[i][each + 1] = RMas[i]; }
SMas[i] = Blocal[i][0]; MPI.COMM_WORLD.Send(SMas, 0, ln, MPI.FLOAT, myrank – 1, 200); MPI.COMM_WORLD.Recv(RMas, 0, ln, MPI.FLOAT, myrank - 1, 200); for(int i = 0; i < ln; i++ ) Alocal[i + 1][0] = RMas[i];
myrank - 1, myrank - 1,
} if(myrank < size - 1) { for(int i = 0; i < ln; i++) SMas[i] = Blocal[i][each - 1]; MPI.COMM_WORLD.Send(SMas, 0, ln, MPI.FLOAT, myrank + 1, 200); MPI.COMM_WORLD.Recv(RMas, 0, ln, MPI.FLOAT, myrank + 1, 200); for(int i = 0; i < ln; i++ ) Alocal[i + 1][each + 1] = RMas[i]; }
myrank + 1, myrank + 1,
}
Рис. 15. Итерационный цикл. Завершение программы: Перед выходом из программы необходимо вызвать метод Finalize(), который завершает работу библиотеки MPI.
Рис. 14. Локализация удаленных данных.
MPI.Finalize(); } catch(MPIException e) { System.out.println(e.toString()); }
Итерационный цикл: В этом цикле осуществляются вычисления для каждой части массива. После каждой итерации необходимо произвести обновление значений теневых граней. /* Итерационный цикл */ for(int k = 0; k < iternum; k++)//the main loop { for(int i = 1; i <= ln; i++) for(int j = 1; j <= each; j++) Blocal[i - 1][j - 1]=(float)0.25*(Alocal[i-1][j]+ Alocal[i+1][j]+Alocal[i][j-1]+Alocal[i][j+1]); // Обновление локального массива коэффициентов for(int i = 0; i < ln; i++) for(int j = 1; j < each + 1; j++) if((i != 0)&&(i != ln - 1)) Alocal[i][j] = Blocal[i - 1][j - 1]; //Обновление теневых граней. if(myrank > 0) { for(int i = 0; i < ln; i++)
23
}
Рис. 16. Завершение программы. Как видно из примеров, программа, разработанная средствами Java-DVM, имеет некоторые преимущества: Модель Java-DVM скрывает от разработчика параллельных программ уровень передачи сообщений, реализуя параллелизм программы классами своей библиотеки. Однако тут надо отметить, что методы классов библиотеки Java-DVM используют вызовы MPI для организации взаимодействия процессов. Используемая модель дает более наглядное представление о распределении данных и вычислений, поскольку архитектура виртуальной вычислительной среды и способы распределения данных задаются самим разработчиком. Программы, использующие библиотеку Java-DVM, легко модернизировать. Например, предположим, что в представленном выше примере программы необходимо изменить способ распределения массива - yраспределение на 2d-распределение. В случае программы на Java+MPI
24
пришлось бы добавить в код новые логические блоки, реализующие такой способ отображения массива на процессоры. Для этого в программе, разработанной средствами Java-DVM, для этого достаточно передать в качестве параметра конструктору, создающему распределенный массив, указатель на объект, реализующий 2d способ распределения, как показано ниже. DoubleDArray da = new DoubleDArray(new 2dDistribution(vpm, ln, ln)); Кроме того, DVM предоставляет средства отладки и анализа параллельных программ в определениях собственной модели. Однако при рассмотрении модели Java-DVM как средства разработки параллельных программ необходимо учитывать следующее. Количество способов отображения данных на процессоры ограниченно. Кроме того, модель определяет структуры данных, которые могут быть распределены. Есть также ограничения на архитектуру вычислительной среды. Можно сказать, что, с одной стороны, модель Java-DVM ограничивает своими определениями класс решаемых задач, с другой, позволяет разрабатывать эффективные параллельные программы в рамках определенной прикладной области.
5. А.И. Аветисян, И.В. Арапов, С.С. Гайсарян, В.А. Падарян. “Среда ParJava для разработки SPMD-программ для однородных и неоднородных сетей JavaVM.” Труды Института Системного Программирования Российской Академии Наук. Том 2, 2000. 6. JAVA 2 SDK, Standard Edition http://java.sun.com/products/jdk/1.2/ 7. PVM: Parallel Virtual Machine, home page. http://www.epm.ornl.gov/pvm/pvm_home.html 8. С.С. Гайсарян, М.В. Домрачёв, В.Ф. Еч, О.И.Самоваров, А.И. Аветисян. “Параллельное программирование в среде Java для систем с распределенной памятью. Объектные модели параллельного выполнения.” Труды Института Системного Программирования Российской Академии Наук, Том 1, 1999. 9. В.П. Иванников, С.С. Гайсарян, М.В. Домрачев, О.И. Самоваров. “Объектная модель DVM и ее реализация на языке Java.” Вопросы Кибернетики. Приложения системного программирования. Выпуск 4. 1998 10. Н.А.Коновалов, В.А.Крюков, А.А.Погребцов, Ю.Л.Сазанов. “С-DVM - язык разработки мобильных параллельных программ”. Препринт ИПМ им. М.В.Келдыша РАН №86, 1997.
4. Заключение В данной статье была рассмотрена возможность использования объектных моделей высокого уровня для разработки эффективных программ с параллелизмом по данным. Была представлена объектная модель Java-DVM. Также проведено сравнение двух параллельных программ. Первая программа была разработана с использованием модели Java-DVM, вторая - средствами языка Java, расширенного библиотекой MPI . Объектные модели параллелизма представляют собой технологию, способную обеспечить все этапы разработки эффективных параллельных программ: проектирование, реализацию и отладку. В настоящее время ведется работа над объектной реализацией средств отладки параллельных Java-DVM программ. Литература: 1. MPI: Message Passing Interface Standard, Message Passing Interface Forum, 2000; http://www.mcs.anl.gov/mpi/index.html 2. MPI: Message Passing Interface Standard, Message Passing Interface Forum, 2000; http://www.mcs.anl.gov/mpi/index.html 3. Rajkumar Buyya (ed.) "High Performance Cluster Computing": Programming and Applications. Vol. 2. Prentice Hall PTR, New Jersey, 1999. 4. MPI: Message Passing Interface Standard, Message Passing Interface Forum, 2000; http://www.mcs.anl.gov/mpi/index.html
25
26
иногда – жесткие диски и/или другие устройства ввода/вывода. К системе могут быть добавлены специальные узлы ввода-вывода и управляющие узлы. Узлы связаны через некоторую коммуникационную среду (высокоскоростная сеть, коммутатор и т.п.). Существуют различные проекты таких суперкомпьютеров: Option Red фирмы Intel [2], SR8000 Series фирмы Hitachi [3] др. Они различаются по типу используемых процессоров, однако основное их различие – подход к организации коммуникационных подсистем. Сложность используемой коммуникационной подсистемы определяет и стоимость проекта.
Среда ParJava для разработки SPMDпрограмм для однородных и неоднородных сетей JavaVM∗ А.И. Аветисян, И.В. Арапов, С.С. Гайсарян, В.А. Падарян Аннотация. В статье дается общее описание среды ParJava, которая является расширением среды Java средствами разработки масштабируемых, эффективных, переносимых, объектно-ориентированных параллельных программ, как для однородных, так и для неоднородных параллельных вычислительных систем с распределенной памятью. При этом инструментальная вычислительная система, на которой разрабатывается программа, может быть как однородной, так и неоднородной. Среда позволяет использовать алгоритмы, разработанные для однородных систем, на неоднородных системах без потери масштабируемости, т.е. делает их переносимыми. В состав среды включены низкоуровневые средства (библиотека Java-классов), обеспечивающие возможность разработки, реализации и выполнения параллельных программ в модели параллелизма по данным (SPMD) на однородных и неоднородных вычислительных системах. В дальнейшем эти средства позволят эффективно реализовывать объектные модели параллельного программирования более высокого уровня. 1. Мы изучаем возможности разработки и реализации параллельных программ для многопроцессорных вычислительных систем с распределенной памятью в модели SPMD [1]. Целью является реализация простых в использовании и эффективных средств разработки переносимых масштабируемых параллельных программ для таких систем. Для поддержки параллельности в системах с распределенной памятью обычно используется механизм процессов и передачи сообщений. Прикладные параллельные программы для суперкомпьютеров с массивно-параллельной архитектурой разрабатываются, как правило, на последовательных языках, расширенных библиотеками передачи сообщений. Массивно-параллельные системы состоят из одинаковых вычислительных узлов, включающих:
Самым производительным суперкомпьютером, на данный момент, является массивно-параллельная система ASCI White корпорации IBM [4]. Система объединяет 8192 процессора на медной основе с общей пиковой производительностью в 12.3 TFLOPS (триллионов операций в секунду). Она включает в общей сложности 8 TB (миллионов мегабайт) оперативной памяти, распределенной по 16-процессорным SMP-узлам, и 160 TB дисковой памяти. Все узлы системы работают под управлением ОС AIX – варианта UNIX от IBM. Среда программирования для ASCI White включает реализации интерфейсов MPI [5] и OpenMP [6] – международные стандарты интерфейсов передачи сообщений соответственно на распределенной и общей памяти. В настоящее время в связи с появлением стандартного высокопроизводительного коммуникационного оборудования (Fast Ethernet [7], Myrinet [8] и др.) широкое распространение получают вычислительные кластеры с распределенной памятью. Их основное достоинство – их аппаратное обеспечение состоит из стандартных процессоров и коммуникационного оборудования массового производства, что позволяет использовать программное обеспечение, разработанное для локальных сетей (например, ОС Linux [9], различные реализации интерфейса MPI и др., не только коммерческие, но и свободно распространяемые). Следствием этого является высокое соотношение производительность/стоимость, возможность модификации путем замены микропроцессоров, коммуникационных сред и версий программного обеспечения. Примерами таких систем являются: Linux-кластер на основе двухпроцессорных серверов Eximer, кластер AliCE компании Compaq и др. Сведения о вычислительных кластерах приведены в таблице 1, заимствованной из [10].
один или несколько центральных процессоров (обычно RISC), локальную память (прямой доступ к памяти других узлов невозможен), коммуникационный процессор или сетевой адаптер, ∗
Работа поддерживалась грантом РФФИ 99-01-00206
27
28
Таблица 1. Вычислительные кластеры и их операционные системы. Организация/п роект
N
LANL/Avalon
14 0
НИВЦ МГУ
12
ИВВиБД, "Паритет"
4
ИСОИ РАН
4
OSC
32
CTC "AC3 Velocity"
64
Indiana Uni.
32
NCSA/NT Supercluster
64
AHPCC/ Roadrunner
64
Paderborn Uni./PSC1
32
Paderborn Uni./PSC
96
LANL/ Pathforward
12 8
Sandia/Cplant
40 0
Конфигурация узла Alpha 21164/533MHz, 256 MB RAM, 3.2 GB HDD Dual Pentium III/500MHz, 256 MB RAM, 3.2 GB HDD 2 x Pentium II/450MHz, 512MB RAM, 10GB HDD 2 x Pentium II/400MHz, 512MB RAM, 9 GB HDD Сервер SGI 1400L: 4 x Pentium III Xeon/500 DELL PowerEdge – 4 x Pentium III Xeon/500MHz, 4GB RAM, 54GB HDD. Compaq ProLiant – 2xPentium II/400MHz 2-процессорные раб. станции HP Kayak XU, процессоры Pentium III/450MHz и Pentium II/300MHz 2xPentium II/450MHz, 512MB RAM, 6.4GB HDD SNI Celsius 2000E – 2xPentium II/300MHz SNI Primergy – 2 x Pentium II/450MHz, 512 MB RAM, 4 GB HDD. Alpha EV6/500MHz, 1GB RAM Digital Personal Workstation 500a – Alpha/500MHz, 192 MB RAM, без диска
CPU
Сеть
ОС
140
Fast Ethernet + Gigabit Ethernet (в центре).
Linux
24
SCI+ Fast Ethernet.
Red Hat Linux 6.1
8
Myrinet + Fast Ethernet
Linux
8
Fast Ethernet, коммутатор Cisco Catalyst 2912
Linux
128
N/A
Linux
256
Clan
Windows NT/2000
64
Fast Ethernet и Gigabit Ethernet (параллельно)
Windows NT + Linux
128
Myrinet
Windows NT
128
Myrinet
Linux
64
SCI(Dolphin)
Linux
192
SCI (Dolphin)
Solaris 2.6
256
Onet (Quadrics)
Tru64 UNIX
400
Myrinet(для каждого подкластера по 16 узлов)
Linux-кластер, состоящий из 12 двухпроцессорных серверов Eximer с процессорами Pentium III/500 Мгц, имеет пиковую производительность 12 GFLOPS. Он введен в эксплуатацию в НИВЦ МГУ. Вычислительные узлы объединяются в двумерную решетку с помощью высокоскоростной сети SCI [11], а в качестве служебной сети используется Fast Ethernet. Максимальная скорость обмена данными по сети в приложениях пользователя составляет 80 Мбайт/с, а время задержки не превышает 5.6 мкс. В качестве основной среды параллельного программирования в кластере применяется MPI (Message Passing Interface) версии ScanMPI 1.9.1 [12]. Кластер работает под управлением операционной системы Linux Red Hat 6.1 [13]. Производительность на тесте при решении системы линейных уравнений с матрицей 16000×16000 составляет 5.7 GFLOPS. На тестах NPB 2.3 [14] производительность сравнима с показателями суперкомпьютеров семейства CRAY T3E [15]. Кластер AliCE (Alpha Linux Cluster Engine) компании Compaq состоит из 128 процессоров Alpha 21264 [16], установленных в станциях DS10 [17], которые объединены в сеть Myrinet SAN (пропускная способность 1.28 Гбит/с при работе в дуплексном режиме). Параллельные приложения используют Myrinet для внутренних обменов, а для рабочих пересылок, управления и поддержки связи с Internet по протоколу TCP/IP применяются два канала Fast Ethernet. Пиковая производительность составляет 154 GFLOPS (80 GFLOPS по тестам Linpack [18]). Распределенная оперативная память – 16 Гбайт, дисковая – 1 Тбайт. Кластер работает под управлением операционной системы Suse Linux 6.3 [19]. В настоящее время используются также "вычислительные фермы" (compute farm) - кластеры, все узлы которых размещены в одном корпусе. В качестве примеров вычислительных ферм можно упомянуть: ферму на базе рабочих станций HP VISUALIZE J6000. Эта рабочая станция включает до двух процессоров PA-8600 и до 16 GB оперативной памяти. Система включает до 20 таких рабочих станций с общей пиковой производительностью до 88 GFLOPS и суммарной оперативной памятью до 320 GB. Рабочие станции объединяются с помощью коммутатора Cisco Catalyst 3524 XL; ферму на базе плат TPE3 [20]. Плата представляет собой вычислительный узел с процессором G4(400 Мгц), содержащий до 512 Mbytes оперативной памяти. Система включает до 16 таких узлов с общей пиковой производительностью до 45 GFLOPS. Платы расположены на общей PCI шине и, кроме того, объединены в сеть Myrinet. Все вышеперечисленные кластеры используются в качестве дешевого варианта массивно-параллельного компьютера. Они представляют собой однородные вычислительные сети: все процессоры, расположенные в узлах сети одинаковы и, следовательно, имеют одинаковую производительность. Все каналы связи
Linux
29
30
между процессорами имеют одинаковую пропускную способность. Производительность таких кластеров и ферм обычно имеет тот же порядок, что и производительность суперкомпьютеров предыдущего поколения. Стоимость кластеров имеет тот же порядок, что и теперешняя стоимость указанных суперкомпьютеров. Но кластеры требуют существенно меньших расходов на сопровождение, чем суперкомпьютеры, так как не предъявляют повышенных требований к квалификации персонала. Кроме того, кластеры имеют значительно более дешевое системное программное обеспечение. При объединении в кластер компьютеров разной производительности или разной архитектуры, говорят о гетерогенных (неоднородных) кластерах. Во избежание путаницы мы будем называть такие системы неоднородными вычислительными сетями (НВС). Такая ситуация возникает в случае постепенного расширения и модернизации кластеров или ферм; в случае использования локальных компьютерных сетей (в их состав входят рабочие станции, персональные компьютеры и т.п.) как кластеров. В будущем в качестве параллельных систем с распределенной памятью, вероятно, можно будет рассматривать также системы, строящиеся из свободных ресурсов в Internet. В суперкомпьютерах и кластерах мощности процессоров согласованы с пропускной способностью каналов связи. Это обстоятельство необходимо учитывать при построении НВС. Это означает, что не любая локальная компьютерная сеть может рассматриваться как НВС: необходимо, чтобы значения производительностей узлов и пропускных способностей каналов связи различались в допустимых пределах (см. ниже) и чтобы средняя производительность узла была согласована со средней пропускной способностью канала связи. Для разработки программ для параллельных систем с распределенной памятью необходимы специальные языковые средства параллельного программирования. В настоящее время одним из наиболее часто используемых языковых средств является международный стандарт интерфейса передачи сообщений MPI. Большинство параллельных программ, как для суперкомпьютеров, так и для кластеров разрабатываются на языках Fortran+MPI, C+MPI. Сейчас происходит постепенный переход к объектноориентированной технологии разработки параллельных программ. В основном используется язык C++, расширенный библиотеками классов, реализующих функциональность MPI. Набор функций MPI вобрал в себя лучшие черты предшествующих систем передачи сообщений р4 [21], PVM [22] и др. MPI поддерживает несколько режимов передачи данных, важнейшие из которых: синхронная передача, не
31
требующая выделения промежуточных буферов для данных и обеспечивающая надежную передачу данных сколь угодно большого размера, и передача с буферизацией, при которой посылающий сообщение процесс не ждет начала приема, что позволяет эффективно передавать короткие сообщения. MPI позволяет передавать данные не только от одного процесса другому, но и поддерживает коллективные операции: широковещательную передачу, разборку-сборку (scatter, gather), операции редукции. При разработке и реализации параллельных программ для НВС возникают специфические проблемы, связанные с неоднородностью вычислительной сети. Возникает потребность в средствах управления ресурсами, выделяемыми для выполнения параллельной программы (в частности, возникает необходимость динамического изменения ресурсов). Интерфейс MPI разработан для однородных систем, и в нем такие возможности не предусмотрены. Следовательно, НВС требуются дополнительные языковые средства для управления ресурсами системы. Целью настоящей работы является общее описание среды ParJava, предназначенной для разработки параллельных Java-программ, которые могли бы выполняться как на однородных параллельных вычислительных системах (суперкомпьютерах и кластерах), так и на НВС. Среда ParJava включает в себя: языковые средства, в виде набора интерфейсов и классов, расширяющие язык Java возможностями для разработки параллельных программ; инструментальные средства, помогающие в разработке и реализации эффективных масштабируемых параллельных программ. В п. 2 вводится терминология и формулируется цель разработки среды ParJava. В п. 3 проводится сравнение среды Java с другими языковыми средами разработки программ и обосновывается возможность разработки эффективных параллельных программ в среде Java. В п. 4 приводится общее описание среды разработки параллельных программ ParJava. В п. 5 разбирается пример использования среды ParJava для разработки параллельной программы для однородной сети JavaVM и для НВС с балансировкой нагрузки; однородная сеть JavaVM моделировалась на неоднородной вычислительной системе. В заключительном п. 6 содержатся выводы и направления дальнейшего развития системы. 2. Перейдем к строгой постановке задачи разработки среды ParJava. Для этого нам понадобятся следующие определения. Однородной будем называть вычислительную систему, в которой: однородны узлы; однородна коммуникационная среда, т.е. скорость передачи данных для всех существующих в системе каналов связи одинакова.
32
Узлы будем считать однородными, если у них одинаковая аппаратная производительность;
реализация
и
как
следствие
одинаковая
одинаковая вычислительная среда, т.е. одни и те же:
операционная система;
компилятор
редактор связей
символьный отладчик
инструментальная среда программирования
разделяемые библиотеки
библиотеки поддержки времени выполнения
программные средства коммуникационной среды
программные средства организации параллельных вычислений PVM, MPI и др.
В противном случае систему будем называть неоднородной. Следовательно, неоднородность распределенной вычислительной системы может быть трех видов: неоднородность вычислительной среды неоднородность по производительности узлов неоднородность среды коммуникации. Производительность каждого узла параллельной вычислительной системы (а также производительность всей вычислительной системы) измеряется с помощью специальных программ, называемых бенчмарками. Это связано с тем, что производительность системы может существенно различаться на разных классах задач. Поэтому для каждого класса задач используются свои бенчмарки. В среде Java разработаны бенчмарки для многих классов задач [23]. Набор этих бенчмарков постоянно пополняется. Бенчмарки для однородных и неоднородных сетей Java-исполнителей могут быть разработаны на основе бенчмарков на языках Fortran+MPI, C+MPI для параллельных вычислений в модели SPMD.
Параллельная вычислительная система называется масштабируемой, если производительность системы пропорциональна сумме производительностей всех ее узлов. Для однородной системы масштабируемость можно определить и как пропорциональность ее производительности числу ее узлов. Для каждой масштабируемой вычислительной системы существует максимальное число узлов (оно определяется архитектурой системы) такое, что при большем числе узлов система перестает быть масштабируемой. Масштабируемость параллельной программы это линейная зависимость скорости ее выполнения от производительности масштабируемой вычислительной системы. Если система неоднородна по производительностям узлов, то ее масштабируемость зависит не только от количества ее узлов, но и от их относительной производительности (отношения производительности данного узла к суммарной производительности системы). Вычислительные эксперименты показывают, что когда относительная производительность одного или нескольких узлов системы меньше некоторого числа p, система перестает быть масштабируемой. Число p для каждой системы может быть определено с помощью вычислительных экспериментов на бенчмарках. Мы будем называть его допустимой степенью неоднородности системы. Под переносимостью последовательной программы мы будем понимать возможность ее выполнения на любой платформе без каких-либо модификаций или преобразований, а также без потери эффективности. Под переносимостью параллельной программы мы будем понимать возможность ее выполнения на любой масштабируемой вычислительной системе без каких-либо модификаций или преобразований, с сохранением условия масштабируемости. Параллельные программы могут быть переносимы: на однородных вычислительных системах; на неоднородных вычислительных системах; на произвольных вычислительных системах. Отметим, что программа, переносимая на однородных системах, может быть не переносима на НВС даже в случае, если у нее однородны вычислительная и коммуникационная среды (т.е. различны только производительности узлов). MPI.Init(args); int size=MPI.COMM_WORLD.Size(); int rank=MPI.COMM_WORLD.Rank(); nt local_size=S/size+(S%size)/(rank+1); Request req; if (rank==0) { matrx=new int[S*S]; for (int i=0,shift=0;i<size;i++)
При выполнении программы, кроме чистого времени выполнения программы, возникают также накладные расходы. Они возникают в связи с работой операционной системы, библиотек поддержки (например, MPI), JavaVM и т.д. Если накладные расходы ограничены и достаточно малы, то программу будем называть эффективной.
33
34
{ MPI.COMM_WORLD.Isend(matrx,S*shift,S*(S/size +(S%size)/(i+1)),MPI.INT,i,99); shift+=S/size+(S%size)/(i+1);
} } wm=new int[local_size*S]; req=MPI.COMM_WORLD.Irecv(wm,0,local_size*S,MPI.INT,0,99); req.Wait(); res=new int[local_size]; for (int i=0;i
Рис. 1. Параллельная программа, не переносимая с однородных систем на НВС. Рассмотрим параллельную программу (рис.1), которая может выполняться как на однородной системе, так и на НВС, имеющих однородную вычислительную среду. Но она не является переносимой на НВС в смысле нашего определения, т.к. ее перенос на НВС связан с потерей масштабируемости
Таким образом, ставится задача, предоставить прикладному программисту простые, удобные и эффективные средства, позволяющие разрабатывать масштабируемые, эффективные, переносимые, объектно-ориентированные параллельные программы, которые могли бы выполняться как на однородных параллельных вычислительных системах (суперкомпьютерах и кластерах), так и на НВС. 3. Для решения поставленной задачи в качестве среды реализации выбрана среда Java [24]. Основным достоинством Java является полная переносимость программ – программа, написанная с использованием спецификаций системы Java и откомпилированная на одной из платформ, работает на любой программно-аппаратной платформе, на которой установлена система Java, без каких-либо модификаций или преобразований. Последовательную С-программу можно сделать переносимой только внутри фиксированного множества платформ, которое должно задаваться разработчиком с помощью директив псевдокомпиляции, использование которых позволяет разрабатывать программу, выполнимую на всех платформах из указанного множества. Такая же техника может обеспечить переносимость параллельных С-программ в однородных и неоднородных средах из указанного множества платформ, если реализована соответствующая коммуникационная среда (например, библиотека MPI, которая осуществляет передачу данных между всеми этими платформами). Использование языка Java позволяет разрабатывать последовательные и параллельные программы, переносимые между любыми однородными и неоднородными параллельными системами, на которых установлена JavaVM. К положительным свойствам системы Java в аспекте разработки параллельных программ также относятся: простота объектной модели, которая позволяет легко разбираться в исходной программе и производить изменения, дополнения и документирование программы;
Для реализации параллельных программ на неоднородных системах можно использовать следующие подходы:
детерминированность получаемого кода – свойство языка, не позволяющее программисту написать «неправильную» программу, т.е. программу, в которой возможны несанкционированные действия типа обращения к объектам с помощью «висячих» указателей, преобразования случайного участка памяти в экземпляр объекта в результате ошибки в адресной арифметике, и т.п.
балансировка нагрузки на неоднородной сети; моделирование однородной сети на НВС. Очевидно, что в первом случае накладные расходы меньше. Однако моделирование однородной сети снимает проблему переносимости параллельных алгоритмов, разработанных для однородных систем. В дальнейшем, употребляя введенные термины, мы будем вкладывать в них только тот смысл, который был определен выше.
35
Система программирования Java отвечает современным требованиям: поддержка исключительных ситуаций, наличие легковесных процессов (трэдов), потоковый ввод/вывод, поддержка средств сетевого программирования (библиотека сокетов), графический интерфейс пользователя, системы обеспечения безопасности при пересылке данных и байт-кода по сети, и т.д. Кроме того, возможность написания параллельных
36
программ на Java дает возможность пользователям, ранее не имевшим доступа к параллельным вычислительным ресурсам, широко использовать параллельные высокопроизводительные вычислительные комплексы, доступные через Интернет. Основной недостаток среды Java − сравнительно низкая производительность виртуального процессора. Однако использование JIT-компиляторов (или компиляторов реального времени), интегрированных в JavaVM, позволяет получать программы, работающие с такой же скоростью, что и Javaпрограммы, откомпилированные в код компьютера, и примерно с такой же скоростью, что и программы на языке C/C++ (как уже было отмечено, проигрыш в производительности составляет всего 1,5 раза). При этом в JITкомпиляторах используются результаты профилирования программы, что позволяет определить ее узкие места и существенно повысить качество оптимизации. Кроме того, существует большое количество машиннозависимых компиляторов (Native compilers), осуществляющих компиляцию Java-программ в выполняемый двоичный код. Такие компиляторы входят в состав следующих сред разработки: Code Warrior Professional 2.0 фирмы Metrowerks;
В среде Java параллельные программы реализуются на сети, состоящей из виртуальных машин Java. Это позволяет использовать параллельные Javaпрограммы на произвольных параллельных системах (однородных, неоднородных и даже системах, которые могут быть построены из свободных ресурсов в Internet). Единственным условием для этого является наличие на каждом узле системы виртуальной машины Java. Таблица 2. Сравнение производительностей на бенчмарках
Optimized C Code Java 1.0.2 Java 1.1.6 Java 1.2 beta 4 Java 1.2.1
sieve
loop
memory
method
float point
linpack
121
830
378
11029
276
21730
13 20
26 45
7 10
55 109
60 91
641 990
189
203
109
135
65
10630
211
412
205
141
107
13895
Таким образом, для реализации параллельных программ на сетях JavaVM можно использовать следующие подходы:
JBuilder Client/Server Suite фирмы Borland;
запуск на каждом узле системы по одной JavaVM и использование полученной неоднородной сети JavaVM.
Java Workshop фирмы Sun; Power/J Enterprise 2.x фирмы Sybase;
моделирование однородной сети Java-исполнителей на неоднородной параллельной вычислительной системе.
SuperCede for Java 2.0 Professional Edition фирмы SuperCede; Visual Café for Java 2.x (Professional Edition или Database Development Edition) фирмы Symantec. Следует отметить, что даже прямые статические компиляторы для Java не позволяют достичь такого же уровня производительности, который возможен в среде C/C++. Это объясняется тем, что Java-программа остается объектноориентированной и во время выполнения (в отличие от программ C++). Это обеспечивает большую гибкость Java-программ по сравнению с программами среды C/C++ (например, из-за возможности использования рефлексии), но это является причиной того, что технологии статической оптимизации, хорошо зарекомендавшие себя в компиляторах традиционных языков программирования, далеко не всегда могут столь же эффективно применяться при компиляции Java-программ. Это можно рассматривать как плату за преимущества использования объектно-ориентированной технологии, которые могут оказаться важнее различий в производительности, в том числе для параллельных программ.
4. Реализована среда ParJava, позволяющая редактировать, отлаживать и выполнять параллельные программы на однородных и неоднородных сетях JavaVM, а также моделировать однородные сети JavaVM на неоднородных вычислительных системах. Среда запускается на одном из узлов параллельной вычислительной системы (в дальнейшем мы будем называть этот узел корневым; при отображении списка доступных узлов этот узел помечается словом root). На рис. 2 показана часть главного окна системы во время редактирования параллельной программы, разрабатываемой в среде ParJava.
Сравнение производительностей на некоторых бенчмарках для различных реализаций JavaVM и оптимизированного кода C приведено в таблице 2.
37
38
Run – выполнить программу в последовательном режиме на корневом узле. Run on Homogeneous Net – запустить SPMD-программу на однородной сети JavaVM, моделируемой на текущей подсети с оптимальным или заданным пользователем количеством узлов. Run on Heterogeneous Net – запустить SPMD-программу на неоднородной сети JavaVM; на каждом узле системы запускается одна JavaVM; узлы, не соответствующие условию масштабируемости, исключаются.
Рис. 2. Часть главного окна системы ParJava во время редактирования параллельной программы. В тексте редактируемой программы все вызовы параллельных функций выделяются отдельным цветом (на рис. 2 они выглядят более бледными). Кроме стандартных возможностей по редактированию последовательной программы (окна File, Edit, View, Goto, Help), в среде ParJava имеются средства, поддерживающие разработку и выполнение параллельных программ на параллельной вычислительной системе (в частности, на локальной сети), на которой установлена среда ParJava. Некоторые из этих средств содержатся в меню Tools (на рис. 2 показано выпадающее окно с этим меню). Меню Tools содержит следующие инструменты: New Net – выделить подсеть. При вызове этого пункта на экране появится диалоговое окно со списком идентификаторов доступных узлов параллельной вычислительной системы; пользователь отмечает узлы, из которых он хочет сформировать сеть; на этой сети и будет запускаться параллельная программа. Hosts Performance – определить относительную производительность узлов выделенной сети. При определении относительной производительности узлов учитываются параметры программы, определенные при анализе программы (меню Analyzers). Compile – скомпилировать SPMD-программу; запускается компилятор Java из среды JDK 1.2 [25].
39
Trace Visualization (см. ниже). Основным требованием к параллельной программе является ее масштабируемость. При выполнении параллельной программы на неоднородной вычислительной сети возникают вопросы, связанные с эффективным использованием ресурсов системы. Для обеспечения масштабируемости программы разработчику полезно знать ее профили. Для эффективного распределения программы по узлам неоднородной сети необходимо знать значения параметров программы, определяющих фактическую скорость ее выполнения на каждом узле сети. Для определения этих свойств программы в среду ParJava (меню Analyzers) включены следующие инструменты: Instrumentate – инструментирует программу, т.е. вставляет в нее отладочные обращения к таймеру и выдаче. Profile – составляет динамический профиль программы. Test_mode – переводит параллельную программу в тестовый режим, в котором она будет выполняться (окно Tools) с использованием специальной отладочной библиотеки. Средства Instrumentate и Profile позволяют оценить затраты времени на выполнение последовательной части программы на этапе ее разработки и отладки. Это позволяет учитывать вес последовательной части при вычислении производительности узлов, обеспечивая большую производительность сети при выполнении программы. В режиме Test_mode каждая ветвь параллельной программы накапливает историю параллельного исполнения в специальном файле. В этом файле отражаются все события, связанные с параллельным исполнением, а также абсолютное время выполнения как ветви в целом, так и время между параллельными событиями в этой ветви. К таким событиям, например, относятся все вызовы коммуникационных функций. Специальный файл содержит также дополнительную информацию о событии (размер сообщений, от кого кому, номер строки в исходной Java программе и т.д.). Действия по
40
построению этого файла осуществляются автоматически при помощи отладочной библиотеки и не требуют дополнительных усилий со стороны пользователя. Визуализировать накопленную во время выполнения параллельной программы историю можно из среды, выбрав подпункт TraceVizualization, пункта меню Tools. Пример такой визуализации показан на рис. 3.
из функций MPI. Внизу показана временная линейка. При помощи нее можно определить (в миллисекундах), когда произошел вызов той или иной функции.
Рис. 4. Ожидание данных. Функции на схеме, ради экономии места и удобства представления отображаются не названиями, а номерами (например, функциям Init() и Finalize() сопоставлены коды 1 и 2 соответственно). При наводке зеленого курсора на тот или иной квадрат с кодом функции, появляется подсказка с именем функции и относительным временем ее вызова. Работа параллельной программы начинается с запуска функции Init() (код 1), а заканчивается функцией Finalize() (код 2). На схеме эти обрамляющие функции выделены оранжевым цветом. На схеме некоторые квадратики соединены зелеными линиями; длина зеленой линии пропорциональна времени ожидания внешнего события (например, ожидание данных) данной функцией. На рис. 4 показано, как процесс вызвал функцию получения массива данных Recv (код 22), подождал их, и вышел из стадии ожидания, получив нужную порцию данных. Время ожидания выделено зеленым цветом. Процент времени простоя каждого процесса будет вычислен и отображен (в процентах) на диаграмме любого из процессов, если нажать на соответствующую кнопку слева от него. Простои процесса в миллисекундах отобразятся на гистограмме. Чтобы получить диаграмму всех процессов, надо нажать кнопку All. Отображения запуска программ можно сохранять неоднократно – это делается автоматически. Имена файлов данных отличаются двумя последними цифрами. Первая из них – номер запускаемой программы, последняя – номер процесса. Рис. 3. Пример визуализации процессов На приведенном рисунке можно увидеть, как программа TraceVisualization демонстрирует работу семи процессов. Здесь каждая линия – это отдельный процесс параллельной программы. Каждый квадратик на линии – вызов одной
41
При загрузке файла данных работы любого процесса программы автоматически загружаются остальные процессы этой программы. При начальном отображении схемы отрезки времени между вызовами функций масштабируются так, чтобы вся картина работы программы целиком отобразилась на экране. В дальнейшем масштаб изображения может быть изменен. Пользователь может выделить участок трассы двумя красным
42
границами (рис. 5.) и нажать кнопку Zoom In. Тогда этот кусок растянется на весь экран. При помощи Zoom Out таким же путем можно увеличить размеры просматриваемого отрезка времени. Передвигаться по схеме можно при помощи полосок скроллинга.
∂u ∂ ⎛ ∂u ⎞ , ⎜ k ⎟ + F ( x, t ) = cρ ∂t ∂x ⎝ ∂x ⎠ где u=u(x,t) и x – точка n-мерного пространства. В двумерной квадратной области 1×1 уравнение принимает вид
∂u ∂ ⎛ ∂u ⎞ ∂ ⎛ ∂u ⎞ ⎜ k ⎟ + ⎜⎜ k ⎟⎟ + F ( x, y, t ) = cρ , ∂x ⎝ ∂x ⎠ ∂y ⎝ ∂y ⎠ ∂t
u ( x, y, t ),
0 < x < 1,0 < y < 1,0 < t .
Начальные и граничные условия соответственно:
u
t =0
= ϕ ( x , y ),
0 ≤ x ≤ 1,0 ≤ y ≤ 1
u x =0 = ψ 1 ( y, t ), u x =1 = ψ 2 ( y, t ), 0 ≤ y ≤ 1,0 ≤ t , u y =0 = ψ 3 ( x, t ), u y =1 = ψ 4 ( x, t ), 0 ≤ x ≤ 1,0 ≤ t . В качестве функций ϕ и ψ были выбраны
x1 = ( x − 12 ) 2 , y1 = ( y − 12 ) 2
(при
e − ( x1 + y1 ) и 100 * e − ( x1 + y1 ) где
соответствующих
границе
значений
переменных). Программа была перенесена с C на Java практически без изменений. Распараллеливание происходит за счёт распределения узлов сетки между разными процессорами – она «нарезается» на прямоугольники вдоль оси y. Каждый процессор обсчитывает свою матрицу (часть общей матрицы) до достижения требуемой точности. Когда на всех процессорах будет достигнута требуемая точность, выполнение параллельной программы завершается. Тестирование проходило при двух выбранных наборах параметров. В первом случае время расчётов в итерации было значительно больше времени пересылок данных; во втором случае эти времена были соизмеримы. В каждом случае программа работала в трёх конфигурациях: Рис. 5. Выделение участка для просмотра 5. В качестве примера использования среды ParJava рассмотрен параллельный алгоритм, разработанный в рамках курсовой работы на кафедре математической физики ВМиК МГУ. В ней рассматривалось линейное уравнение теплопроводности, и была составлена параллельная масштабируемая программа на языке С для компьютера Parsytec GC. Линейное уравнение теплопроводности имеет вид
43
1. На каждом узле системы запускалось по одной JavaVM, данные были равномерно распределены по ветвям параллельной программы. 2. Моделировалась однородная оптимальная сеть Java-исполнителей; данные по ветвям параллельной программы были распределены равномерно. 3. Моделировалась неоднородная сеть JavaVM, данные были распределены пропорционально относительной производительности узлов системы.
44
Абсолютное время выполнения программы для каждой из перечисленных конфигураций приведены на рис. 6 и 7 (соответственно для первого и второго случая).
Рис. 7. Абсолютное время выполнения программы в случае, когда время расчётов в итерации соизмеримо со временем пересылок данных. Рис. 6. Абсолютное время выполнения программы в случае, когда время расчётов в итерации было значительно больше времени пересылок данных Первая серия тестов (сетка – квадрат со стороной 350 узлов, временной шаг 0,001 сек). На расчёт одной итерации затрачивалось примерно 300 мсек., на пересылки данных за итерацию уходило не более 5 мсек., что дало общее время расчета 612 секунд. Во второй конфигурации на измерение производительностей узлов и моделирование однородной сети потребовалось 35 сек. (5,72%). Вторая серия тестов (сетка – квадрат со стороной 50 узлов, временной шаг 0,0001 сек.) На расчёт одной итерации затрачивалось примерно 15 мсек., на пересылки данных за итерацию уходило не более 1 мсек., что дало общее время расчета 118 секунд. Во второй конфигурации на измерение производительностей узлов и моделирование однородной сети потребовалось 37 сек. (31%). 6. В статье описана среда ParJava, которая является расширением среды Java средствами разработки масштабируемых, эффективных, переносимых, объектно-ориентированных параллельных программ, как для однородных, так и для неоднородных параллельных вычислительных систем с распределенной памятью. При этом инструментальная вычислительная система, на которой разрабатывается программа, может быть как однородной, так и неоднородной. Среда также позволяет использовать алгоритмы, разработанные для однородных систем, на неоднородных системах без потери масштабируемости, т.е. делает их переносимыми.
45
Среда ParJava находится в состоянии развития. Разрабатывается полноценный отладчик параллельных программ, использующий в своей работе отладочную библиотеку и средства инструментирования программ и с их помощью поддерживающий процесс разработки масштабируемых параллельных программ. Разрабатываются новые анализаторы. Расширение языка Java низкоуровневыми возможностями параллельного программирования дает возможность эффективно реализовывать объектные модели параллельного программирования более высокого уровня DPJ[26], DVM[27] и др. Включение этих моделей в среду ParJava позволит существенно облегчить разработку параллельных программ, так как оптимальное распределение данных по узлам параллельных вычислительных систем будет производиться автоматически. Основным достоинством среды ParJava является то, что параллельная программа, разработанная при помощи этой среды, может выполняться на любой масштабируемой вычислительной системе без каких-либо модификаций или преобразований, с сохранением условия масштабируемости. Это снимает многие проблемы по распространению параллельных программ. Параллельные Java-программы немного уступают по производительности параллельным программам на языке C. Это можно рассматривать как плату за преимущества использования объектно-ориентированной технологии разработки и переносимости разработанных параллельных программ. Литература: 1. Rajkumar Buyya (ed.) "High Performance Cluster Computing": Programming and Applications. Vol. 2. Prentice Hall PTR, New Jersey, 1999. 2. An Overview of the Intel TFLOPS Supercomputer http://developer.intel.com/technology/itj/q11998/articles/art_1d.htm
46
3. HITACHI SR8000 Series Super Technical Server http://www.hitachi.co.jp/Prod/comp/hpc/eng/sr81e.html 4. ASCI White http://www.rs6000.ibm.com/hardware/largescale/supercomputers/asciwhite/ 5. MPI: Message Passing Interface Standard, Message Passing Interface Forum, 2000; http://www.mcs.anl.gov/mpi/index.html 6. OpenMP: Simple, Portable, Scalable SMP Programming http://www.openmp.org/ 7. 100 Mbps Fast Ethernet http://wwwhost.ots.utexas.edu/ethernet/100mbps.html 8. Myrinet Index Page http://www.myri.com/myrinet/index.html 9. Linux Online http://www.linux.org/ 10. Сервер НИВЦ МГУ http://www.parallel.ru/ 11. What is the Scalable Coherent Interface http://sunrise.scu.edu/WhatIsSCI.html 12. Hybrid MPI/OpenMP programming for the SDSC teraflop system http://www.npaci.edu/online/v3.14/SCAN.html 13. On-line Resources for Red Hat Linux 6.1 http://www.redhat.com/support/docs/rhl61.html 14. The NAS Parallel Benchmarks http://www.nas.nasa.gov/Software/NPB/ 15. Performance of the Cray T3ETM Multiprocessor http://www.cray.com/products/systems/crayt3e/paper1.html 16. The Alpha 21264 microprocessor http://www.microprocessor.sscc.ru/alpha-21264/ 17. Compaq AlphaServer DS10, Compaq AlphaStation DS10 http://www5.compaq.com/products/quickspecs/10398_na/10398_na.html 18. Linpack Benchmark -- Java Version http://netlib2.cs.utk.edu/benchmark/linpackjava/ 19. SuSE Linux 7.0 http://www.suse.com/en/index.html 20. PowerPC 750/7400 PCI Module http://www.transtech-dsp.com/powerpc/tpe3.htm 21. The p4 parallel programming system. 2000. http://www-fp.mcs.anl.gov/~lusk/p4/index.html 22. PVM: Parallel Virtual Machine, home page. http://www.epm.ornl.gov/pvm/pvm_home.html 23. The industry standard Java benchmark. Pendragon Software http://www.webfayre.com/pendragon/cm3/ 24. Java documentation & training. 2000. http://developer.java.sun.com/developer/infodocs/index.shtml 25. JAVA 2 SDK, Standard Edition http://java.sun.com/products/jdk/1.2/
26. С.С. Гайсарян, М.В. Домрачёв, В.Ф. Еч, О.И.Самоваров, А.И. Аветисян. “Параллельное программирование в среде Java для систем с распределенной памятью. Объектные модели параллельного выполнения.” Труды Института системного программирования Российской академии наук, Том 1, 1999. 27. В.П. Иванников, С.С. Гайсарян, М.В. Домрачев, О.И. Самоваров. “Объектная модель DVM и ее реализация на языке Java.” Вопросы Кибернетики. Приложения системного программирования. Выпуск 4. 1998
47
48
запуск на каждом процессоре распределенной вычислительной системы одной JavaVM, в результате чего получается, вообще говоря, неоднородная сеть Java-исполнителей;
Библиотека интерфейсов и классов, расширяющих язык Java средствами разработки параллельных программ в модели SPMD∗ А.И. Аветисян, В.А. Падарян
моделирование однородной сети Java-исполнителей на неоднородной параллельной вычислительной системе путем запуска нескольких JavaVM на части процессоров для балансировки нагрузки. Моделирование однородной Java-сети может использоваться при разработке параллельных алгоритмов для однородных параллельных вычислительных систем (в частности, суперкомпьютеров и однородных кластеров), для обеспечения переносимости алгоритмов, разработанных для однородных систем, на неоднородные вычислительные системы, а также для исследования свойств параллельных алгоритмов. Среда ParJava включает в себя:
Аннотация. В статье описываются языковые средства, а именно набор интерфейсов и реализующих их классов, которые обеспечивают возможность параллельного программирования на однородных и неоднородных сетях JavaVM. Указанные интерфейсы и классы составляют расширение языка Java для параллельного программирования в модели параллелизма по данным (SPMD). Рассматриваемые интерфейсы и реализующие их классы расширяют язык Java низкоуровневыми возможностями реализации параллельных программ на однородных и неоднородных вычислительных системах. В дальнейшем это даст возможность эффективно реализовывать объектные модели параллельного программирования более высокого уровня.
1. В связи с появлением на рынке дешевых и надежных высокопроизводительных коммуникационных систем, позволяющих строить однородные и неоднородные кластеры на базе процессоров массового производства [1], разработка и использование параллельных программ становится особенно актуальной. Возникает потребность в простых и эффективных языковых средствах, поддерживающих разработку параллельных программ. Одним из таких средств является среда ParJava [1], обеспечивающая разработку масштабируемых переносимых параллельных программ в модели SPMD [2] на языке Java. В среде ParJava параллельные программы реализуются на сети JavaVM (виртуальных Java-машин [3]). Это позволяет использовать параллельные Javaпрограммы на произвольных параллельных вычислительных системах (суперкомпьютерах, однородных и неоднородных кластерах, а также системах, которые могут быть построены из свободных сетевых ресурсов в Internet). Для реализации параллельных программ на сетях JavaVM в среде ParJava используются следующие подходы:
∗
Работа поддерживалась грантом РФФИ 99-01-00206
49
языковые средства в виде набора интерфейсов и классов, расширяющие язык Java возможностями для разработки параллельных программ; инструментальные средства, помогающие в разработке и реализации эффективных масштабируемых параллельных программ. Целью данной работы является описание языковых средств, а именно набора интерфейсов и реализующих их классов, которые обеспечивают возможность параллельного программирования на однородных и неоднородных сетях JavaVM. Указанные интерфейсы и классы составляют расширение языка Java для параллельного программирования в модели SPMD. Инструментальные средства среды ParJava рассмотрены в работе [1]. Алгоритмы балансировки нагрузки, позволяющие обеспечить оптимальное распределение данных по узлам сети, в данной работе не рассматриваются. Они будут опубликованы в дальнейшем. Мы различаем системы параллельного программирования высокого и низкого уровня. В рамках высокоуровневой модели пользователь не занимается передачей сообщений “вручную”, а использует для передачи данных и синхронизации примитивы, описанные в этой модели. Примером системы высокого уровня является JavaParty [4] (хотя, это система распределенного, а не параллельного программирования), а такие средства, как, например, MPI [5] и PVM [6], являются моделями низкого уровня. Каждая система параллельного программирования высокого уровня поддерживается средствами низкого уровня. Так, например, система JavaParty опирается на низкоуровневый интерфейс RMI [7]. Рассматриваемые в статье интерфейсы и реализующие их классы расширяют язык Java низкоуровневыми возможностями реализации параллельных программ на однородных и неоднородных вычислительных системах. В дальнейшем это даст возможность эффективно реализовывать объектные
50
модели параллельного программирования более высокого уровня, такие как DPJ[8], DVM[9]. В п. 2 описывается иерархия и общая функциональность интерфейсов и классов, расширяющих язык Java низкоуровневыми возможностями реализации параллельных программ. В п. 3 описываются интерфейсы IJavaNet, IFullGraph, INetProperties. В интерфейсе IJavaNet вводится понятие вычислительного пространства как неструктурированного нумерованного множества Java-исполнителей, которые связаны каждый с каждым. Каждой сети Java-исполнителей можно сопоставить полный взвешенный граф (вес узла – относительная производительность Javaисполнителя, вес ребра – пропускная способность канала связи между соответствующими Java-исполнителями в сети). В интерфейсе INetProperties специфицированы методы сопоставления полного взвешенного графа, отражающего свойства данной сети Java-исполнителей, к этой сети, а также методы, специфицирующие требования программы к структуре вычислительного пространства. Методы, специфицирующие понятие полного взвешенного графа, определены в интерфейсе IFullGraph.
возможности низкоуровневого параллельного программирования с распараллеливанием по данным для систем с распределенной памятью, без изменения спецификации самого языка. Иерархия интерфейсов и классов, расширяющих язык Java низкоуровневыми возможностями реализации параллельных программ на однородных и неоднородных вычислительных системах, приведена на рис. 1. IJavaNet
IFullGraph
Список методов см. на рис. 2.
Список методов см. на рис. 3.
INetProperties
В п. 4 приводится спецификация текущей версии Java-интерфейса к пакету MPI, который используется в качестве прототипа среды коммуникации.
Список методов см. на рис. 4.
В п. 5 описывается интерфейс IНeterogenNet, в котором специфицируются методы позволяющие моделировать оптимальную неоднородную сеть Javaисполнителей на данной неоднородной параллельной вычислительной системе и реализовывать эффективные низкоуровневые параллельные программы на ней. В п. 6 описывается интерфейс IHomogenNet, в котором специфицируются методы, позволяющие моделировать однородную сеть Java-исполнитлей на данной неоднородной параллельной вычислительной системе и реализовывать эффективные низкоуровневые параллельные программы на ней.
IHeterogenNet
IHomogenNet
Список методов см. на рис. 6.
Список методов см. на рис. 7.
В п. 7 разбирается пример параллельной Java-программы, демонстрирующий возможности рассмотренных интерфейсов. В заключительном п. 8 содержатся выводы и направления дальнейшего развития описанных интерфейсов. Библиотека классов, реализующих интерфейсы, описанные в данной работе, а также более подробное описание среды ParJava доступны по Internet на сайте www.ispras.ru/~javap.
Рис. 1. Иерархия интерфейсов, расширяющих язык Java средствами параллельного программирования в модели SPMD.
2. В среде Java запрещены любые изменения спецификаций как языка Java, так и его интерпретатора JavaVM. Это правильное решение, так как такие изменения сделали бы практически невозможным выполнение Java-программ в произвольной сети и повлекли бы за собой серьезные ограничения в переносимости программ. Поэтому в работе рассматривается функциональное расширение языка Java с помощью библиотек системных классов, добавляющих
В этих интерфейсах вводится понятие вычислительного пространства как Javaсети, на которой выполняется параллельная программа. Каждой сети ставиться в соответствие взвешенный граф, который отражает свойства этой сети (узлы – производительности Java-исполнителей, дуги – пропускные способности каналов связи). Определены интерфейсы и классы, позволяющие моделировать однородную сеть Java-исполнителей на неоднородной параллельной
51
52
вычислительной системе, а также реализовывать параллельные программы на неоднородных сетях Java-исполнителей. При этом в обоих случаях производится балансировка нагрузки с учетом производительностей процессоров и пропускных способностей каналов связи.
номер первого узла текущей сети, номер ее последнего узла и целое число, равное постоянному приращению номеров узлов; метод cloneNet создает подсеть, совпадающую с данной сетью; метод size позволяет получить количество узлов сети;
3. В интерфейсе IJavaNet (рис. 2) специфицируются операции (методы) порождения сетей Java-исполнителей и их подсетей, а также операции их преобразования. Под сетью Java-исполнителей понимается неструктурированное пронумерованное множество Java-исполнителей, которые могут обмениваться сообщениями. Никаких предположений относительно однородности сети не делается (для задания однородности или неоднородности сети используются интерфейсы, специфицируемые ниже). public interface IJavaNet{ public IJavaNet createNet(int[] executor); // создать подсеть public IJavaNet createNet(int first, int last, int stride); // создать подсеть рublic IJavaNet cloneNet(); // построить сеть, совпадающую с данной public int size(); //получить количество узлов в сети public int rank(); //получить порядковый номер узла в сети public boolean isIncl(); // public IJavaNet union(IJavaNet net); //получить объединение net и данной сети public IJavaNet intersection(IJavaNet net); //получить пересечение net и данной сети public IJavaNet complement(); //получить дополнение данной сети до родительской public IJavaNet getParent(); //получить родительскую сеть public IJavaNet getRoot(); //получить корневую (root) сеть в иерархии }
Pис. 2. Интерфейс IJavaNet. Каждая подсеть Java-исполнителей также является сетью, имеет родительскую сеть (подсеть) и может иметь произвольное количество дочерних подсетей. Внутри одной сети (подсети) отсутствуют ограничения на обмен данными между узлами. Сеть Java-исполнителей, у которой нет родительской сети, назовем корневой. Интерфейс IJavaNet включает в себя следующие методы: методы createNet позволяют создать сеть (подсеть) Javaисполнителей из узлов текущей сети; параметром первого метода createNet является массив, содержащий номера узлов текущей сети, которые требуется включить в формируемую подсеть; второй метод createNet имеет три параметра, которые задают, соответственно,
53
метод rank позволяет получить порядковый номер узла в сети; метод getParent позволяет получить родительскую сеть для данной сети; метод getRoot позволяет получить корневую сеть в иерархии; операции над сетями: метод union создает новую сеть как объединение указанной и данной сетей; метод intersection создает новую сеть как пересечение указанной и данной сетей; метод complement создает дополнением данной сети.
новую
сеть,
которая
является
При реализации программ с использованием класса JavaNet, реализующего интерфейс IJavaNet, вычислительное пространство создается запуском на каждом узле параллельной вычислительной системы одного Java-исполнителя. В интерфейсе IJavaNet не специфицированы возможности определения неоднородности вычислительного пространства. Предполагается, что параллельная программа выполняется на однородной вычислительной системе, в которой все узлы связаны со всеми. Отметим, что вычислительное пространство (Java-сеть) можно представить в виде полного взвешенного графа, в котором вес ребра соответствует скорости передачи данных между Java-исполнителями, вес вершины - относительной производительности Java-исполнителя. Масштабируемые параллельные программы (SPMD) могут выполняться на сетях с различным числом узлов, поэтому программа не должна содержать описание сети, на которой она будет выполняться. В ней могут содержаться лишь требования к локальной структуре (топологии) сети. Структура требуемой сети, вообще говоря, определяется тем, между какими узлами происходит обмен сообщениями, и может быть получена из кода программы, либо может специфицироваться пользователем. Методы интерфейса IFullGraph (рис. 3) специфицируют понятие полного взвешенного графа. public interface IFullGraph { public int getGraphSize(); public void setNode(int node,int value);
54
public public public public public public public public
void setNodes(int[] values); void setNodes(int first,int stride,int[] values); int getNode(int node); int[]getNodes(); int[]getNodes(int first,int stride); void setEdge(int from,int to,int value); void setEdges(int[][] values); void setEdges(int first_from,int first_to,int stride_from,int stride_to,int[][] values); public int getEdge(int from,int to); public int[][] getEdges(); public int[][] getEdges(int first_from,int first_to,int stride_from,int stride_to); public void setEdgesFrom(int from,int[] values); public void setEdgesTo(int to,int[] values); }
{ public public public public public public }
Рис. 4. Интерфейс INetProperties. 4. В качестве прототипа среды коммуникации используется библиотека Javaклассов, реализующих объектно-ориентированный интерфейс MPI [6], который был реализован для языка С++ [10]. Современное состояние Java-интерфейса к пакету MPI показано на рис. 5. Этот интерфейс может использоваться в Javaпрограммах отдельно от всей системы.
Рис. 3. Интерфейс IFullGraph. Интерфейс INetProperties (рис. 4) расширяет интерфейсы IJavaNet и IFullGraph. В нем специфицируются методы, позволяющие определять свойства Java-сети, в случае если она неоднородна. Эти свойства бывают необходимы как для моделирования оптимальной однородной сети, так и для моделирования оптимальной неоднородной сети Java-исполнителей на данной неоднородной Java-сети. Кроме того, в интерфейс INetProperties входят методы, определяющие требования программы к топологии вычислительного пространства (линейка, двумерная решетка, звезда и др.). Интерфейс IJavaNet включает в себя следующие методы: метод createFullGraph строит соответствующий данной Java-сети; метод getP позволяет получить неоднородности [1] для данной сети;
полный
взвешенный
значение
void createFullGraph(); int getP(); NetProperties excludeNodes(); void net_1dGrid(); void net_2dGrid(); void net_star();
граф,
В настоящее время в состав среды ParJava включена прототипная реализация интерфейса JavaMPI. Соответствующие Java-классы реализованы посредством Java Native Interface [3] с помощью вызовов стандартных функций языка С++, реализующих соответствующую функциональность MPI (используется свободно распространяемая версия MPI lam6.3 [10]). В дальнейшем этот интерфейс будет реализован на Java. 5. При реализации параллельных программ на неоднородных сетях Javaисполнителей возникает необходимость неравномерного распределения данных с целью эффективного использования ресурсов системы. Отметим, что в отличие от высокоуровневых моделей параллельного программирования, где такое распределение автоматически делается системой поддержки, а способ распределения задается примитивами модели, в низкоуровневых моделях этим необходимо заниматься вручную. Хотелось бы предоставить пользователю простые и эффективные инструменты. public class Cartcomm extends Intracomm; public class CartParms; public class Comm; public class Datatype; public class Errhandler; public class Graphcomm extends Intracomm; public class GraphParms; public class Group; public class Info; public class Intercomm extends Comm; public class Intracomm extends Comm; private class Maxlock extends User_function; private class Minlock extends User_function; public class MPI; public class MPIException;
коэффициента
метод excludeNodes позволяет получить из данной неоднородной сети Java-исполнителей новую сеть, в которой исключены все узлы, не соответствующие условию масштабируемости; методы net_1dGrid, net_2dGrid, метод net_star дают возможность задать топологию формируемой сети (линейка Javaиспонителей, двумерная решетка, или звезда); в дальнейшем список таких методов будет расширен. public interface INetProperties extends IJavaNet,IFullGraph
55
56
public public public public public public
class class class class class class
Op; Prequest extends Request; Request; ShiftParms; Status; User_function;
Рис. 5. Java-интерфейс к пакету MPI. Для этого интерфейс INetProperties расширен интерфейсом IHeterogenNet (рис. 6), в котором специфицируются следующие методы: метод relativePerformanceHost вычисляет производительность узла с запрашиваемым номером; метод myrelativePerformance вычисляет производительность текущего узла;
После того как оптимальная сеть Java-исполнителей будет создана (при ее создании учитываются производительности узлов, измеренные на бенчмарках, и требования программы к топологии сети, моделируемой на данной параллельной вычислительной системе), можно достичь более эффективного использования ресурсов системы, распределяя данные пропорционально производительности ее узлов. Однако в случае, когда время выполнения последовательных частей параллельной программы (SPMD) сравнимо с временем выполнения ее параллельных частей, этого не достаточно. В этом случае на этапе разработки и отладки программы необходимо оценить затраты времени на выполнение последовательных частей, что даст возможность учесть время выполнения последовательных частей при вычислении производительностей узлов и тем самым обеспечить более высокую производительность сети при выполнении программы. Для этого можно воспользоваться инструментами Instrumentate и Profile меню Analyzers среды ParJava [1]. public interface IHeterogenNet extends INetProperties{ public void relativePerformanceHost(int hostnumber); public void myrelativePerformance(); public void createHeterogenNet(); public void heterogenGather(Object sendbuf, int sendcount, Datatype sendtype, Object recvbuf, int recvcounts[], int displs[], Datatype recvtype, int root); public void heterogenScatter(Object sendbuf, int sendcounts[], int displs[], Datatype sendtype, Object recvbuf, int recvcount, Datatype recvtype, int root); }
метод netpower вычисляет сумму относительных мощностей всех узлов сети; метод rectstaken вычисляет сумму производительностей узлов неоднородной сети с первого до текущего узла включительно; метод createHeterogenNet создает неоднородную сеть, в которой на каждом физическом узле системы запущена одна JavaVM, исключены узлы, несоответствующие условию масштабируемости, и которая оптимизирована в соответствии с требованием программы к топологии сети; метод heterogenGather собирает в приемный буфер данного узла передающие буферы остальных узлов (позволяет задавать разное количество отправляемых данных в разных узлах-отправителях); метод heterogenScatter рассылает части передающего буфера неодинаковой длины в приемные буферы неодинаковой длины.
Рис. 6. Интерфейс IHeterogenNet. 6. Интерфейс IHomogenNet (рис. 7) расширяет интерфейс INetProperties. В нем определены методы, позволяющие на данной неоднородной сети создавать однородную сеть Java исполнителей: метод getMinPermissibleNumberHosts вычисляет минимальное допустимое количество узлов в однородной сети, моделируемой на данной неоднородной сети;
Производительность каждого узла параллельной вычислительной системы (а также производительность всей вычислительной системы) измеряется с помощью специальных программ, называемых бенчмарками. Это связано с тем, что производительность системы может существенно различаться на разных классах задач. Поэтому для каждого класса задач используются свои бенчмарки. В среде Java разработаны бенчмарки для многих классов задач [11]. Набор этих бенчмарков постоянно пополняется. Бенчмарки для однородных и неоднородных сетей Java-исполнителей могут быть разработаны на основе бенчмарков на языках Fortran+MPI, C+MPI для параллельных вычислений в модели SPMD. Бенчмарки дают возможность измерить производительности узлов неоднородной сети на рассматриваемом классе задач.
57
метод getMaxPermissibleNumberHosts вычисляет максимальное допустимое количество узлов в однородной сети, моделируемой на данной неоднородной сети; метод createHomogenNet с параметром hostsnumber создает однородную сеть с заданным количеством узлов на данной неоднородной сети; метод createHomogenNet создает оптимальную однородную сеть на данной неоднородной сети.
58
Однородные сети моделируются с учетом требований программы к топологии сети. public public public public public }
interface IHomogenNet extends INetProperties { int getMinPermissibleNumberHosts(); int getMaxPermissibleNumberHosts(); IHomogenNet createHomogenNet(); IHomogenNet createHomogenNet(int hostsnumber);
Рис. 7. Интерфейс IHomogenNet. 7. В качестве примера использования описанной библиотеки интерфейсов и классов рассмотрим параллельный алгоритм, разработанный в рамках курсовой работы на кафедре математической физики факультета ВМиК МГУ. В ней рассматривалось линейное уравнение теплопроводности, и была составлена параллельная масштабируемая программа на языке С для компьютера Parsytec GC. Линейное уравнение теплопроводности имеет вид:
∂ ⎛ ∂u ⎞ ∂u , ⎜ k ⎟ + F ( x, t ) = cρ ∂x ⎝ ∂x ⎠ ∂t где u=u(x,t) и x - точка n-мерного пространства. В двумерной квадратной области 1×1 уравнение принимает вид:
∂ ⎛ ∂u ⎞ ∂ ⎛ ∂u ⎞ ∂u ⎜ k ⎟ + ⎜⎜ k ⎟⎟ + F ( x, y, t ) = cρ , ∂x ⎝ ∂x ⎠ ∂y ⎝ ∂y ⎠ ∂t
u ( x, y, t ),
0 < x < 1,0 < y < 1,0 < t .
Начальные и граничные условия соответственно
u
t =0
= ϕ ( x , y ),
0 ≤ x ≤ 1, 0 ≤ y ≤ 1
u x =0 = ψ 1 ( y, t ), u x =1 = ψ 2 ( y, t ), 0 ≤ y ≤ 1,0 ≤ t , u y =0 = ψ 3 ( x, t ), u y =1 = ψ 4 ( x, t ), 0 ≤ x ≤ 1,0 ≤ t . В качестве функций ϕ и ψ были выбраны
e − ( x1 + y1 ) и 100 * e − ( x1 + y1 ) где
x1 = ( x − 12 ) 2 , y1 = ( y − 12 ) 2
(при соответствующих границе значений переменных). Решение поставленной задачи производится методом сеток. Двумерная квадратная область разбивается на квадратики со стороной h (шаг разностной сетки). Значения функций в узлах разностной сетки рассматриваются как
59
разностные функции, приближающие коэффициенты уравнения, начальные данные и решение уравнения. В результате исходное уравнение превратится в разностное уравнение, которое представляет собой систему линейных алгебраических уравнений с квадратной матрицей А размера n×n, где n=1/h. Распараллеливание происходит за счёт распределения столбцов матрицы A между разными процессорами. Каждый процессор обсчитывает свою матрицу (часть матрицы A) до достижения требуемой точности. Когда на всех процессорах будет достигнута требуемая точность, выполнение параллельной программы завершается. В случае однородной сети на каждый процессор рассылается одинаковое число столбцов матрицы A (обозначим его через D). Поскольку для вычисления конечных разностей необходимы соседние узлы, имеет смысл загрузить на каждый процессор по дополнительному столбцу справа и слева (дублирование данных оправдывается сокращением количества пересылок). Поэтому фактическое число столбцов матрицы A на процессоре равно M=D+2. В случае неоднородной сети ей сопоставляется однородная сеть (производительность каждого узла неоднородной сети кратна производительности узлов однородной сети), на каждый процессор которой рассылается одинаковое число (D) столбцов матрицы A. Следовательно, на каждый процессор неоднородной сети будет загружено M=D*K+2 столбцов матрицы A. На рис. 8 приведены тексты программ, реализующие этот метод для следующих трёх конфигураций вычислительной сети: На каждом узле системы запускалось по одной JavaVM, данные были равномерно распределены по ветвям параллельной программы. Программа была перенесена с C на Java практически без изменений (использовался Javaинтерфейс к MPI). На рис. 8 это соответствует не закомментированным строкам текста. Моделировалась однородная оптимальная сеть Java-исполнителей; данные по ветвям параллельной программы были распределены равномерно. Использовался класс HomogenNet, реализующий интерфейс IHomogenNet. На рис. 8 это соответствует закомментированным “/**” строкам текста. Моделировалась неоднородная сеть JavaVM, данные были распределены пропорционально относительной производительности узлов системы. Использовался класс HeterogenNet, реализующий интерфейс IHeterogenNet. На рис. 8 это соответствует закомментированным “/*” строкам текста. В первом случае создается вычислительное пространство – Java-сеть, в которой на каждом узле параллельной вычислительной системы с распределенной памятью будет запущена одна JavaVM (рис. 8, строка 5), на полученной сети JavaVM выполняется параллельная программа. Программа реализована из
60
предположения, что параллельная система однородна (класс JavaNet не предоставляет никаких возможностей по управлению ресурсами системы). Во втором случае на данной системе моделируется однородная сеть JavaVM, которая и является вычислительным пространством для параллельной программы (рис. 8, строка 6). Это позволяет в случае неоднородности вычислительной системы балансировать нагрузку в сети. Становится возможным выполнение программ, разработанных для однородных вычислительных систем на неоднородных вычислительных системах, а также разрабатывать программы для однородных систем на имеющейся неоднородной вычислительной системе (например, на локальной сети). В третьем случае создается вычислительное пространство – Java-сеть (объект класса HeterogenNet), в которой на каждом физическом узле системы запущена одна JavaVM, исключены узлы, не соответствующие условию масштабируемости (рис. 8, строка 7). Класс HeterogenNet предоставляет средства для определения и эффективного использования ресурсов параллельной системы. 1. import ru.ispras.ParJava.*; 2. import java.util.*; 3. class HeatTransport { 4. public static void main(String args[]) 5. { JavaNet net = new JavaNet(); 6. /** HomogenNet net = new HomogenNet(); 7. /* HeterogenNet net = new HeterogenNet(args); 8. int pid = net.rank(); //номер текущего узла 9. int P = net.size(); //количество узлов сети 10. int PROCQ = P; 11. /* int PROCQ = net.netpower(); /* метод netpower() вычисляет сумму относительных производительностей всех узлов сети*/ 13. int gridFrequency = 50; //количество подобластей, // на которые разбивается // обсчитываемая область 14. int M, K, D, S; 15. /* D – количество столбцов матрицы, размещаемых на узле с единичной производительностью */ 16. D=(gridFrequency-2)/PROCQ; 17. // M – количество столбцов матрицы, размещаемых на // текущем узле 18. M=D+2; 19. /* M=D*relativePerformanceHost(pid)+2; 20. K=D*PROCQ+2; //приведенное количество //подобластей, на которые //разбивается обсчитываемая область 21. S = D*pid; 22. /* S = D*net.rectstaken();
/* метод rectstaken() вычисляет сумму относительных производительностей узлов неоднородной сети с первого до текущего узла включительно */ 24. // [ Инициализация остальных переменных. ] 25. // [ Вычисление начальных условий.] 26. for(m = 0; m < M; m++ ) 27. { for(k = 0; k < K; k++) 28. { 29. xx1 = (S + m) * h1 - a/2; 30. xx1 = xx1 * xx1; 31. yy1 = k * h2 - b/2; 32. yy1 = yy1 * yy1; 33. // продолжение вычисления начальных условий 34. } 35. } 36. while (allContin != 0) { 37. // [Основной цикл параллельной части программы] 38. } 39. // Обработка полученных результатов 40. }
рис. 8. Фрагмент SPMD-программы решения уравнения теплопроводности. В программе вводится переменная PROCQ, которая содержит суммарную относительную производительность всех узлов сети. В случае однородного вычислительного пространства она равна количеству узлов в сети (рис. 8, строка 10). В случае неоднородного вычислительного пространства суммарная относительная производительность всех узлов сети определяется при помощи метода, реализованного в классе HeterogenNet (рис. 8, строка 11). Количество столбцов матрицы, размещаемых на узле с единичной производительностью, является значением переменной D (рис. 8, строка 16). Поскольку в однородном случае абсолютная производительность всех узлов одинакова, то относительная производительность каждого узла равна 1 и на каждый узел необходимо распределить D столбцов. Но, как было отмечено выше, вычисление конечных разностей связано с использованием соседних столбцов матрицы. Для всех D столбцов загруженных на рассматриваемый узел, кроме первого и последнего, соседние столбцы находятся на этом же узле. Поэтому, чтобы сделать цикл по столбцам однородным, имеет смысл загрузить на рассматриваемый узел по дополнительному столбцу справа и слева (как в однородном, так и неоднородном случае). Поэтому общее число узлов загружаемых на узел в однородном случае, равно не D, а M=D+2 (рис. 8, строка 18). В неоднородном случае число загружаемых столбцов пропорционально относительной производительности узла (рис. 8, строка 19). Абсолютный номер первого из D столбцов, размещенных на текущем узле, определяется по номеру узла (pid) в однородном случае (рис. 8, строка 21) и с
61
62
помощью метода rectstaken() в неоднородном случае (рис. 8, строка 22). В строках 26-35 вычисляются начальные условия для текущего узла. Последующий текст программы не зависит от однородности вычислительного пространства (рис. 8, строки 36 и далее до конца программы). На рис. 9 представлены фрагменты программы, в которых производится прием и передача правых столбцов матрицы. // Ожидание данных в текущей ветви параллельной программы // от предыдущей ветви параллельной программы необходимых // для следующей итерации(правый столбец учаска матрицы // предыдущей ветви параллельной программы) // wm – буфер приема; M*K – смещение в буфере приема // начиная с которого помещаются принимаемые данные; K+1 – // количество (элементов в столбце) принимаемых данных; // net.DOUBLE – тип принимаемых данных; pid-1 – номер узла // от которого ожидаются данные net.Recv(wm, M*K,K+1,net.DOUBLE,pid-1,200); // Посылка текущей ветвью параллельной программы правого // столбца учаска матрицы к последующей ветви параллельной // программы // wm – буфер передачи; M*K+(M-2)*K - смещение в буфере // передачи начиная с которого отправляются данные; K+1 – // количество (элементов в столбце) передаваемых данных; // net.DOUBLE – тип передаваемых данных; pid+1 – номер узла // которому посылаются данные net.Send(wm, M*K+(M-2)*K,K+1,net.DOUBLE,pid+1,200);
Рис. 9. Использование функций коммуникационной библиотеки. 8. В статье описано языковое расширение среды Java библиотеками интерфейсов и классов, позволяющими реализовывать масштабируемые, эффективные, переносимые, объектно-ориентированные параллельные программы, как для однородных, так и для неоднородных параллельных вычислительных систем с распределенной памятью. Это расширение является частью среды ParJava [1]. Отметим, что разработанные библиотеки интерфейсов и классов являются низкоуровневым расширением языка Java для разработки параллельных программ. Эти интерфейсы и классы позволяют эффективно реализовывать объектные модели параллельного программирования более высокого уровня DPJ, DVM и др., что существенно облегчит разработку параллельных программ, так как оптимальное распределение данных по узлам параллельных вычислительных систем будет производиться автоматически.
может выполняться на любой масштабируемой вычислительной системе без каких-либо модификаций или преобразований, с сохранением условия масштабируемости. Это снимает многие проблемы по распространению параллельных программ. Параллельные Java-программы уступают по производительности параллельным программам на языке C. Однако это различие не очень существенно (например, как показали расчеты на компьютере для теста Linpack [12] производительность JavaVM из среды JDK 1.2 [3] в 1,5 раза меньше C/C++). Его можно рассматривать, как плату за преимущества использования объектно-ориентированной технологии разработки и абсолютной переносимости разработанных параллельных программ. Литература: 1. А.И. Аветисян, И.В. Арапов, С.С. Гайсарян, В.А. Падарян. “Среда ParJava для разработки SPMD-программ для однородных и неоднородных сетей JavaVM.” Труды Института Системного Программирования Российской Академии Наук. Том 2, 2000. 2. Rajkumar Buyya (ed.) "High Performance Cluster Computing": Programming and Applications. Vol. 2. Prentice Hall PTR, New Jersey, 1999. 3. JAVA 2 SDK, Standard Edition http://java.sun.com/products/jdk/1.2/ 4. M. Philippsen, M. Zender, “JavaParty – Transparent Remote Objects in Java”, In Proceedings of ACM PPoPP Workshop on Java for Science and Engineering Computation, 1997 5. MPI: Message Passing Interface Standard, Message Passing Interface Forum, 2000; http://www.mcs.anl.gov/mpi/index.html 6. PVM: Parallel Virtual Machine, home page. http://www.epm.ornl.gov/pvm/pvm_home.html 7. Java Remote Method Invocation (RMI) http://java.sun.com/products/jdk/1.2/docs/guide/rmi/index.html 8. С.С. Гайсарян, М.В. Домрачёв, В.Ф. Еч, О.И.Самоваров, А.И. Аветисян. “Параллельное программирование в среде Java для систем с распределенной памятью. Объектные модели параллельного выполнения.” Труды Института Системного Программирования Российской Академии Наук. Том 1. 1999. 9. В.П. Иванников, С.С. Гайсарян, М.В. Домрачев, О.И. Самоваров. “Объектная модель DVM и ее реализация на языке Java.” Вопросы Кибернетики. Приложения системного программирования. Выпуск 4. 1998. 10. LAM/MPI Parallel Computing. LAM Team/UND. 1996-2000. http://mpi.nd.edu/lam/index.html 11. The industry standard Java benchmark. Pendragon Software. http://www.webfayre.com/pendragon/cm3/ 12. Linpack Benchmark -- Java Version http://netlib2.cs.utk.edu/benchmark/linpackjava /
Основным преимуществом использования описанных интерфейсов и классов является то, что параллельная программа, разработанная при помощи них,
63
64
увеличении степени вложенности циклов с одновременным уменьшением числа повторений внутренних циклов. Результаты экспериментов подтверждают эффективность этого оптимизирующего преобразования для реализации редуктивных выражений.
Применимость тайлинга для компиляции редукций в языке C[] А. Калинов, А. Ластовецкий, И. Ледовских, М. Посыпкин
1. Введение Вычисления над массивами данных широко распространены. В языках типа FORTRAN, C, PASCAL и многих других такие вычисления записываются с помощью циклов. В связи с распространенностью подобного рода вычислений, ряд современных языков FORTRAN90, FORTRAN95, ZPL [ZPL], C[] [Cbr, Cbr1] помимо обычных операций над данными скалярного типа также имеют операции над массивами. Эти операции мы будем называть векторными операциями, а выражения и операторы в которых они фигурируют – векторными выражениями и операторами соответственно. Векторные операции позволяют с одной стороны более компактно выражать алгоритмы, содержащие вычисления над массивами, а с другой стороны – предоставляют компилятору больше информации о структуре алгоритма, которую можно использовать при генерации оптимального кода. Операции над массивами делятся на поэлементные, когда операция применяется к соответствующим элементам массивов одинаковых размерностей, и редукции, когда одна и та же операция применяется к элементам или группам элементов некоторого массива, при этом размерность результата операции меньше размерности операнда. Примером редукции может служить операция SUM в FORTRAN90, которая вычисляет сумму элементов либо подмассивов некоторого массива. В процессе компиляции произвольное векторное выражение заменяется последовательностью базовых векторных операторов, каждый из которых затем транслируется в одну систему вложенных циклов. Важным часто встречающимся классом базовых векторных операторов является простой редуктивный оператор (более подробно это понятие рассматривается в разделе “Синтаксис C[] и понятие редуктивного выражения”). В редуктивных операторах результат редукции используется повторно в получаемой системе вложенных циклов. В подобной ситуации можно заметно ускорить выполнение программы, если предотвратить, либо уменьшить вытеснение элементов результата из кэша. С этой целью применяется тайлинг [Lam, Wolfe]. Суть этого преобразования заключается в
65
Анализ корректности применения тайлинга для произвольной системы вложенных циклов не является тривиальной задачей [Lam, Wolfe]. В [Wolfe] доказывается критерий применимости тайлинга к системам идеально вложенных циклов. В данной работе показывается, что система вложенных циклов, получаемая в результате компиляции любого простого редуктивного оператора, удовлетворяет этому критерию. Это означает, что при применении тайлинга к таким системам вложенных циклов анализ корректности не требуется, что позволяет существенно упростить алгоритм генерации кода для редуктивного оператора.
2. Синтаксис C[] и понятие редуктивного выражения Язык C[] [Cbr, Cbr1], является строгим расширением ANSI C. Основным новым понятием, введенным в C[], является понятие вектора. Вектор определяется как упорядоченная последовательность значений одного произвольного типа. Принципиальным отличием вектора от массива является то, что элементы вектора вовсе не обязаны регулярно располагаться в памяти как элементы массива. Элементами вектора также могут быть вектора. В языке Си массив в арифметических выражениях преобразуется к типу “указатель на тип элемента”. Поэтому в языке C[] предусмотрена операция, которая предотвращает преобразование массива к указателю и, тем самым, позволяет использовать его в арифметических выражениях как единое целое – операция вырезки. Операция вырезки предназначена для обеспечения доступа к сегментам массивов. Она имеет следующий синтаксис: e [l : r : s], где e – выражение, обозначающее массив, а выражения l, r, s имеют целый тип и обозначают левую границу, правую границу и шаг вырезки соответственно. При этом, e [l : r : s] обозначает вектор из (r-l)/s + 1 элементов, где i-м элементом этого вектора является e[l + i * s]. Например, если массив а состоит из пяти элементов, то выражение a[2 : 4 : 2] обозначает вектор длины 2 , элементами которого являются a[2] и a[4]. С помощью вырезки можно получать доступ к различным совокупностям элементов не только одномерных, но и многомерных массивов. Если шаг вырезки равен 1, то его можно не указывать, второе двоеточие тоже при этом можно опустить. Правая и левая границы также могут быть опущены.
66
Опущенная левая граница считается равной 0, а опущенная правая считается равной N-1, где N – число элементов массива, к которому применяется вырезка. Таким образом, значением выражения a[:] является вектор, состоящий из всех элементов массива a.
то терминальными элементами вектора v будут все терминальные элементы его элементов.
Выражение, образованное применением нескольких операций вырезки к обозначению массива, будем называть тривиальным векторным выражением.
Выражение, содержащее векторные операции, называется векторным выражением. Векторные выражения можно условно разделить на два класса – поэлементные и редуктивные. Поэлементным называется векторное выражение, не содержащее редуктивных операций. Выражение вида [ω]Ψ, где Ψ – поэлементное выражение, будем называть редуктивным. Например, a[:] + b[:] – поэлементное выражение, а [*] (a[:] + b[:]) – редуктивное.
Семантика некоторых арифметических операций языка Си и операций присваивания расширена таким образом, что их операндами и результатами могут быть векторные значения. В этом случае, соответствующая операция применяется поэлементно. Например, код для нахождения поэлементной суммы массивов a и b с помещением результата в массив с может иметь следующий вид: double a[N], b[N], c[N]; ... c[:] = a[:] + b[:]; В данном случае, векторный оператор c[:] = a[:] + b[:]; эквивалентен следующему циклу: for(i = 0; i < N; i ++) c[i] = a[i] + b[i]; Некоторым бинарным операциям языка Си поставлены в соответствие редуктивные операции по следующему правилу: если выражение e является Nэлементным вектором, а ω – некоторая бинарная операция, то соответствующая ω редуктивная операция обозначается через [ω], а результат ее применения к e определяется следующим образом: [ω]e = (…((e0 ω e1 ω e2 )… ω eN), где e0, e1,…, eN – компоненты вектора e. Простейшим примером применения редуктивной операции может служить код, вычисляющий сумму строк матрицы: double A[M][N], a[N]; ... a[:] = [+] A[:][:]; Введем понятие ранга вектора. Если элементы вектора не являются векторами, то ранг вектора полагаем равным 1. Если элементы вектора являются векторами размерности n, то ранг вектора полагается равным n + 1. Рангом векторного выражения E, обозначаемого через rank(E), называется ранг вектора, являющегося его значением. Также нам понадобится понятие терминального элемента вектора. Если элементами вектора являются объекты невекторного типа, то они называются его терминальными элементами. Если элементами вектора v являются вектора,
67
3. Компиляция векторных выражений
Редуктивным оператором называется оператор вида Φ = Ψ, где Φ – тривиальное векторное выражение, а Ψ – редуктивное выражение. Поэлементным оператором называется оператор вида Φ = Ψ, где Φ – тривиальное векторное выражение, а Ψ – поэлементное выражение. Например, оператор a[:] = [+] A[:][:]; является редуктивным. При вычислении любого векторного выражения, очевидно, происходит чтение из памяти и, возможно, запись в память некоторых данных. Если векторное выражение не содержит операций присваивания и операций с побочными эффектами, то при вычислении такого выражения не производится запись, а производится только чтение данных из памяти. Множество данных, которые записываются или считываются при вычислении данного векторного выражения Φ, будем называть памятью, используемой данным выражением и обозначать через μ(Φ). Векторное выражение присваивания Φ = Ψ будем называть базовым, если μ(Φ) ∩ μ(Ψ) = ∅. Аналогично, базовым оператором будем называть оператор, состоящий из одного базового выражения. Базовое выражение называется простым, если выражения Ψ и Φ не содержат операций с побочным эффектом [Сstd]. Простым оператором будем называть оператор, состоящий из одного простого выражения. На первом этапе трансляции компилируемое векторное выражение заменяется эквивалентной последовательностью базовых векторных операторов, каждый из которых является либо редуктивным, либо поэлементным. Например, выражение a[:] = [+] A[:][:] * [+] B[:][:] заменяется следующей последовательностью операторов: tmp1[:] = [+]A[:][:]; tmp2[:] = [+]B[:][:]; a[:] = tmp1[:] * tmp2[:]; На последующих этапах трансляции для каждого базового оператора генерируется своя система вложенных циклов. Любой базовый оператор может
68
быть вычислен с помощью одной системы вложенных циклов. Для поэлементного базового оператора E = F; эта система циклов имеет вид:
могут быть вытеснены из кэша. Поэтому целесообразно применить тайлинг этого цикла, в результате чего получится следующий код:
for(i1 = 0; i < N1; i1 ++) /* цикл 1*/ for(i2 = 0; i2 < N2; i2 ++) /* цикл 2*/ ... ... for(in = 0; in < Nn; in++) /* цикл n */ E[i1, i2,..., in] = F[i1, i2,..., in]; где rank(E) = rank(F) = n, а E[i1,i2,...,in] и F[i1,i2,...,in] – терминальные элементы векторов, являющихся значениями выражений E и F с соответствующими индексами. Рассмотрим базовый редуктивный оператор E = [ω] F; где F – поэлементное выражение ранга n, E – вектор ранга n – 1, а [ω] – редуктивная операция. Для вычисления данного редуктивного оператора требуется вычислить значение выражение F, а затем применить к нему редуктивную операцию [ω]. Это можно сделать с помощью следующей системы вложенных циклов: for(i1 = 0; i1< N1; i1 ++) /* цикл 1*/ for(i2 = 0; i2 < N2; i2 ++) /* цикл 2*/ ... ... for(in = 0; in < Nn; in ++) /* цикл n */ if(i==0) E[i2,...,in] = F[i1,i2,...,in]; else E[i2,...,in] ω= F[i1,i2,...,in]; ... Проиллюстрируем описанную схему компиляции на примере редуктивного оператора a[:]=[+]A[:][:]. Данный оператор можно вычислить с помощью следующей системы вложенных циклов: for(i = 0;i < M;i ++) for(j = 0;j < N;j ++) if(i == 0) a[j] = A[i][j]; else a[j] += A[i][j];
/* цикл 1 */ /* цикл 2 */
Заметим, что данные по ссылке a[i] повторно используются в цикле 1. Большое число итераций цикла 2 может препятствовать повторному использованию ссылки a[j], так как к моменту повторного использования данные по ссылке a[j]
69
for(J = 0; J < N; J += T) /* цикл c2 */ for(i = 0; i <M; i ++) /* цикл 1 */ for(j = J; j < min(J + T, N);j ++) /* цикл 2 */ if(i == 0) a[j] = A[i][j]; else a[j] += A[i][j]; Аналогично, в случае произвольного редуктивного оператора, тайлинг циклов 2,...,n применяется для увеличения числа попаданий в кэш для ссылки E[i2,...,in], которая повторно используется в цикле 1. В следующем разделе будет показана корректность такого преобразования для системы циклов, полученной в результате компиляции произвольного простого редуктивного оператора.
4. Применимость тайлинга к простому редуктивному оператору В начале этого раздела мы рассмотрим модель итерационного пространства [Wolfe, Som97], которую обычно используют для анализа применимости тайлинга и других преобразований к системе идеально вложенных циклов. Затем покажем, как можно применить данную модель для случая циклов, получающихся в результате компиляции редуктивного оператора. Пусть имеется система из n идеально вложенных циклов типа for: for(i1 = 0; i1 < N1; i1 ++) for(i2 = 0; i2 < N2; i2 ++) ... for(in = 0; in < Nn ; in ++) { /* тело системы вложенных циклов */
} Итерационным пространством данной системы вложенных циклов называется пространство Zn. Тогда данной системе циклов ставится в соответствие множество всех наборов a из Zn, таких что 0 ≤ a1 < N1, 0 ≤ a2 < N2, …, 0 ≤ an < Nn. Каждой итерации данной системы циклов ставится в соответствие вектор из этого множества, компоненты которого совпадают со значениями соответствующих индексов. Такой вектор называется итерационным вектором данной итерации. Для удобства мы будем говорить “итерация a” вместо “итерация с итерационным вектором a”. На итерационном пространстве Zn можно ввести лексикографический порядок: >. Для пространства Z1 он совпадает с обычным порядком на
70
for(i1 = 0; i1 < N1; i1 ++) /* цикл 1*/ for(i2 = 0; i2 < N2;i2 ++) /* цикл 2*/ ... for(in = 0; in < Nn; in ++) /* цикл n*/ if(i1 == 0) E[i2,...,in] = F[i1,i2,...,in]; else E[i2,...,in] ω= F[i1,i2,...,in]; ...
множестве целых чисел. Предположим, что лексикографический порядок определен для пространств Zi, 1 < i < n. Тогда будем говорить, что вектор b из Zn лексикографически больше, чем вектор a из Zn , и писать b > a, если b1 > a1 либо одновременно b1 = a1 и (b2,…,bn) > (a2,…,an). Из определения лексикографического порядка следует, что итерация b выполняется после итерации a тогда и только тогда, когда вектор b > a в лексикографическом смысле. Если итерация a обращается к некоторому адресу памяти, итерация b обращается к этому же адресу памяти, и при этом хотя бы одно из этих обращений является записью данных, то будем говорить, что итерации a и b имеют зависимость по данным. Согласно условию Бернстайна [Bernstein], преобразование кода программы будет корректным, если порядок выполнения итераций, имеющих зависимость по данным, сохраняется в результате преобразования. Геометрическим выражением зависимости по данным является понятие дистанционного вектора [Lam, Wolfe]. Если итерации a и b имеют зависимость по данным и b > a, то говорят, что имеется дистанционный вектор d = b – a данной системы вложенных циклов. Применимость тайлинга для произвольной системы вложенных циклов исследована в работах [Lam, Wolfe]. Имеют место следующие две теоремы [Wolfe]: Утверждение 1 (Wolfe). Циклы с i-го по j-й могут быть переставлены в любом порядке, если для любого дистанционного вектора d данной системы вложенных циклов (d1, … , di-1) > 0 или dk ≥ 0 для всех i, i ≤ k ≤ j. Циклы, для которых выполнены условия утверждения 1, называются полностью переставляемыми. Утверждение 2 (Wolfe). Тайлинг циклов с i-го по j-й является корректным преобразованием тогда и только тогда, когда эти циклы полностью переставляемы. С помощью этих двух утверждений мы докажем следующую теорему: Теорема 1. Ко всем циклам системы вложенных циклов, полученной в результате компиляции любого простого редуктивного оператора, может быть применен тайлиг. Доказательство. Пусть имеется некоторый простой редуктивный оператор E = [ω] F; где F – поэлементное выражение ранга n, E – вектор ранга n-1, а [ω] – редуктивная операция.
Так как редуктивный оператор E = [ω] F; является простым, то вектора E и F не пресекаются в памяти и выражение F[i1, i2, …, in]; не содержит операций записи в память. Поэтому, зависимость по данным будут иметь итерации, у которых левые части имеют один и тот же адрес в памяти. Этому условию удовлетворяют итерации, итерационные вектора которых отличаются только в первой компоненте. Таким образом, множество дистанционных векторов для рассматриваемой системы вложенных циклов состоит из векторов (k, 0,…, 0), где 1 ≤ k < n. Условие утверждения 1 выполнено для данной системы вложенных циклов. Следовательно, все циклы системы полностью переставляемы, и, согласно утверждению 2, к ним может быть применен тайлинг. Теорема доказана.
6. Результаты экспериментов На основе доказанной теоремы в компиляторе языка C[] реализован алгоритм компиляции редуктивных выражений, использующий тайлинг. Выбор оптимального размера тайла не рассматривается в данной работе. Результаты экспериментов показывают эффективность тайлинга при генерации кода для редуктивных операторов. Для разных редуктивных операторов на различных платформах данный метод позволяет получать 5-25% ускорения. Для иллюстрации рассмотрим задачу нахождения суммы строк матрицы N1 × N2. Соответствующий редуктивный оператор имеет вид: a[:] = [+] A[:][:];. В таблице 1 приводятся значения ускорения, полученного за счет применения тайлинга для платформ Sparc Station 5 и Ultra 1. Платформа Sparc 5
Кэш 8 Kb
N1 × N2 1000 × 1000 1500 × 1500
Ускорение 1.2 1.16
Ultra 1
16 Kb
1000 × 1000 1500 × 1500
1.03 1.08
Таблица 1. Ускорения для оператора a[:] = [+] A[:][:]; .
Система вложенных циклов, вычисляющая данный редуктивный оператор, имеет следующий вид:
71
72
6. Заключение Результат, доказанный в данной работе, позволяет не производить проверку корректности при применении тайлинга к системам циклов, полученных в результате компиляции простых редуктивных операторов. Это существенно упрощает алгоритм генерации кода для таких операторов. Результаты экспериментов подтверждают эффективность тайлинга для оптимизации редуктивных операторов. Литература: [CbrSpec] The C[] Language Specification. http://www.ispras.ru/~cbr/cbrsp.html [Bernstein] A. J. Bernstein. Program analysis for parallel processing. IEEE Transactions on Electronic Computers, EC-15(5):757-762, Oct. 1966. [Cstd] ANSI. Programming Language C. X3.159-1989 American National Standard Institute. [Cbr] S. Gaissaryan, and A. Lastovetsky. ANSI C superset for vector and superscalar computers and its retargetable compiler. Journal of C Language Translation, 5(3):183198, 1994. [Som97] S.Ghosh, M.Martonosi, S. Malik. Cache miss equations: an analitical representation of cache misses. Proceedings of the 11th ACM Conference on Supercomputing, Vienna, Austria, July 1997. [Cbr1} S. Katserov, A. Lastovetsky,S. Gaissaryan, D. Khaletsky, I. Ledovskih. Retargetable compiler for ANSI C superset for vector and superscalar computers. Proceedings of Second International Conference on Software for Multiprocessors and Supercomputers. Theory, Practice, Experience, Moscow, Russia, September 1994. [ZPL] Calvin Lin and Lawrence Snyder. ZPL: An Array Sublanguage. Languages and Compilers for Parallel Computing, pp. 96-114, 1993. [Lam] M. Wolfe, M. Lam. A data locality optimizing algorithm., in ACM SIGPLAN conference on PLDI, June 1991. [Wolfe] M.E. Wolfe, Improving locality and parallelism in nested loops, Ph.D. dissertation, August 1992, Stanford University
73
Проблемы организации объектноориентированного доступа к реляционным базам данных*
масштабы и мощность прикладных систем непрерывно растут вслед за увеличением мощности аппаратуры. При этом большой процент прикладных программ нуждается в долговременном хранении данных, используемых в работе. На основе изучения существующих материалов и программных продуктов можно выделить основные на сегодняшний день технологии хранения, обработки и доступа к данным: реляционная модель, получившая наибольшее распространение модель объектно-ориентированной СУБД
К.В. Антипин, В.В. Рубанов
СУБД иерархической системы (в виде дерева директорий)
Аннотация.
В статье рассматриваются проблемы взаимодействия объектноориентированных программ с реляционными базами данных. На основе анализа различных программных продуктов и международных стандартов сделана попытка выделить общие для всех объектно-ориентированных программ особенности долговременного хранения информации. В качестве одного из решений приводится схема трехуровневой архитектуры доступа к хранимой информации Клиент/Посредник/РСУБД, где Посредник играет роль изолирующей прослойки между объектно-ориентированной и реляционной парадигмами.
1. Введение Объектно-ориентированные (ОО) технологии всё шире внедряются в различные сферы прикладного программирования. Рынок ОО программных продуктов растет с каждым годом. Этот процесс неизбежен и вполне оправдан известными достоинствами ОО подхода: надежность программ, строгая типизация (классы, подклассы и т. п.), фиксация интерфейсов, доступ к данным объектов только через их интерфейсы, механизм исключительных ситуаций, простота проектирования, структурированность программы, и как следствие возможность легкой модификации кода. Одним из главных преимуществ ОО парадигмы над традиционным алгоритмическим программированием является возможность моделирования более сложных и больших задач, что имеет исключительную ценность, поскольку *
Работа поддержана грантами РФФИ № 96-07-89591 и № 97-01-00142. 75
разнообразные версии гибридных СУБД, в которых делаются попытки объединить преимущества различных подходов. Таким образом, с одной стороны просматривается четкая тенденция в развитии объектно-ориентированных программ, а с другой накоплено и используется большое число реляционных баз данных, с которыми эти ОО приложения должны взаимодействовать. При этом, говоря о реляционных базах данных, следует отметить, что их программный интерфейс (API) в большинстве случаев разрабатывался для алгоритмических языков программирования и в результате не приспособлен к ОО концепции. Поэтому возникает ряд трудностей при попытке использования API реляционной БД в ОО приложении, рассмотрению которых и посвящен следующий раздел.
2. Хранение объектов в ОО программах 2.1 ОО программирование и реляционные базы данных: проблемы сосуществования В мире баз данных длительное время развивались и совершенствовались реляционные системы. Создание строгого стандарта языка запросов (SQL) явилось одним из наиболее действенных факторов, повлиявшим на появление множественных реализаций РСУБД и их повсеместное внедрение. Реляционная модель получила мощное развитие за долгие годы ее использования и сейчас применяется практически во всех областях, где используются информационные системы. В большинстве своем приложения для РСУБД написаны на алгоритмических языках (C, Pascal, Fortran, и т. д.) и для доступа к данным используют библиотеки функций прикладного программного интерфейса (API) данной РСУБД. При попытке применить реляционную технологию хранения данных к ОО программам, возникает ряд несоответствий и даже противоречий. Суть этих противоречий кроется в принципиальном различии двух подходов: реляционного и объектно-ориентированного. ОО модель оперирует такими аспектами как данные (информационные элементы), содержащиеся в объектах, поведение объектов, представленное 76
набором методов, и взаимосвязи различного типа между классами этих объектов. Тогда как РСУБД оперирует только данными и предназначена для хранения собственно информационных массивов. При этом для объектной модели характерно наличие таких свойств, как инкапсуляция, наследование и полиморфизм. Объекты в ОО модели органично связаны в некоторую схему, которая находится в довольно простом соответствии с жизненной задачей приложения. Реляционная модель направлена, прежде всего, на именно управление большими объемами абстрактных данных некоторых предопределенных элементарных типов. Все данные хранятся в виде двумерных таблиц (в настоящее время существуют также и многомерные РБД) и в качестве механизма обеспечения целостности данных используются первичные и внешние ключи. Доступ к данным осуществляется путем выполнения SQL запросов, при этом в качестве объекта действия выступает одна или несколько таблиц. Рассмотрим трудности, возникающие при попытке отображения ОО модели на реляционную, то есть при решении задачи хранения объектов в реляционной среде. 1. Инкапсуляция. Реляционные БД не поддерживают средств ограничения доступа, кроме паролей и пользователей. Однако прикладная программа обычно выполняется при одном уровне привилегий и поэтому все приватные данные, хранящиеся в БД, становятся общедоступными, а попытки обеспечить инкапсуляцию путем введения различных представлений (views) с определенными правами доступа ведут к существенному усложнению схемы БД и программного кода. 2. Наследование. Так как в РБД хранятся только данные объектов, то для корректного их воссоздания нужно хранить еще и информацию об их классах. Иерархия классов может быть представлена путем создания отдельных таблиц (таблиц класса) для каждого элемента этой иерархии. При этом для обеспечения корректного выполнения запросов записи для объекта необходимо хранить и во всех таблицах родительских классов и при обработке данного объекта надо следить за правильным использованием всех этих родительских таблиц. 3. Полиморфизм. Поддержка данного механизма в РБД полностью отсутствует, и чтобы обеспечить корректную реконструкцию объектов, нужно следить за наличием достаточной дополнительной информации в таблицах класса. Итак, мы видим, что обеспечение базовых механизмов ОО модели в реляционной БД связано с рядом трудностей, связанных, прежде всего, с необходимостью решать задачу корректного отображения иерархии объектов на реляционную структуру, что зачастую является очень нетривиальным делом. Кроме того, сам прикладной интерфейс РСУБД не соответствует объектным принципам и его использование вкупе с необходимостью хранения объекта в нескольких различных таблицах заметно повышает сложность кода и как следствие нарушает его структурированность, существенно усложняет процесс отладки. При этом SQL-код в явном виде используется в теле 77
приложения, что делает программы негибкими и непереносимыми, так как появляется зависимость приложения от используемой схемы РСУБД (структура таблиц, связи между ними, поля таблиц) и зависимость кода программы от конкретной РСУБД (производителя, а возможно, и версии). Таким образом, попытка непосредственного использования традиционных API реляционной СУБД в ОО среде клиента нивелирует преимущества ОО концепции. В настоящий момент в мире разработано огромное число информационных систем на базе реляционных СУБД. И проблема "сращивания" ОО приложений с РСУБД представляется весьма актуальной из-за наличия большого числа "наследуемых систем" ("legacy systems"). В то же время, в связи с увеличением интереса к ОО программированию, в последнее время получают все большее распространение объектно-ориентированные системы управления базами данных (ООСУБД). Технология ООСУБД явилась альтернативой реляционным базам данных и отчасти была призвана разрешить те несоответствия ОО и реляционного подходов, о которых говорилось выше. Однако её использование подразумевает создание информационной системы «с нуля». Более подробному анализу преимуществ, недостатков и перспектив использования реляционных и объектно-ориентированных СУБД и посвящен следующий подраздел.
2.2 Реляционные и объектно-ориентированные современное состояние и перспективы
СУБД:
Как было отмечено, в настоящее время можно четко выделить два основных направления в хранении данных приложения: использование объектных и реляционных баз данных. При этом в обоих случаях имеются свои преимущества и недостатки. И решение в пользу того или иного направления главным образом определяется самой решаемой задачей. Реляционный подход, будучи хорошо изучен, развит и стандартизован в результате многолетней практики использования, хорошо подходит для задач, оперирующих большими объемами данных, когда критическими являются скорость обработки и возможность формирования сложных составных запросов на выборку данных. Однако для успешного применения РСУБД в совокупности с ОО программами, необходимо иметь специальную архитектуру и технологию хранения объектов в РСУБД. Также нельзя сбрасывать со счетов проблему унаследованных систем – факта существования огромного числа действующих, годами разрабатывавшихся реляционных БД. Революционное внедрение новых технологий (например, ООСУБД) потребовало бы колоссальных вложений на перепроектирование существующих систем и на трансляцию накопленных данных в новую БД – непростую, а в некоторых случаях крайне трудно решаемую задачу, в силу больших размеров и сложности исходной базы. И все это в условиях необходимости непрерывного доступа к транслируемым данным для нормального функционирования 78
предприятия. ООСУБД, несомненно, имеют свою область применения. Существует класс задач (CAD applications, CASE tools и другие), где применение РСУБД не вполне целесообразно, поскольку они не смогут эффективно работать, тогда, как ООСУБД исключительно хорошо удовлетворяют требованиям задачи. Например, в ОО системах автоматизированного проектирования обычно строится модель из сложных, тесно взаимосвязанных объектов. Дизайнер обычно долго манипулирует системой из таких объектов, после чего вся конфигурация должна быть сохранена. Если такое приложение базируется на РСУБД, для создания столь сложных и тесно взаимосвязанных объектов потребуется производить объединение многих таблиц и выполнять много операций для "синтеза" окончательного объекта, что неизбежно скажется на производительности. В этом случае удобнее и быстрее сохранить конфигурацию как объект. Отметим, что ООСУБД являются развивающейся технологией, для которой еще не существует официального промышленного стандарта, однако работы активно ведутся. В 1993 году была создана первая версия стандарта на ООСУБД – ODMG-93. Автором является рабочая группа по объектным базам данных (Object Database Management Group, c 28.04.98 переименована в Object Data Management Group), в состав которой входят наиболее влиятельные в области информационных технологий фирмы. После чего последовала большая работа по исправлению и доработке, которая в результате воплотилась уже в более детальный стандарт ODMG 2.0. Таким образом, просматривается явная тенденция в сторону развития объектно-ориентированных БД. Однако на сегодняшний день и в ближайшем будущем, по-видимому, будут превалировать РСУБД, хотя бы в силу человеческой инертности. При этом следует заметить, что реляционные базы данных выполняют строго предписанную им функцию – хранение данных, и с этой задачей они прекрасно справляются, что вполне оправдывает их использование в любых программах. Проблема же рассогласования двух парадигм представляется более общей. Как пишет автор статьи [8], это проблема сосуществования одной модели с другой несколько сродни идее инкапсуляции, положенной в основу ОО парадигмы. Следует изолировать данные (информацию), которые статичны по своей природе и функции (алгоритмы), непрерывно меняющиеся под влиянием переменных внешних условий. При этом рождается концепция изолирования доступа к данным со стороны программы и создания функционального интерфейса, такого, чтобы программа могла обращаться к этим данным лишь в терминах некоторых функций, несущих определённый смысл в предметной области своей задачи. Это позволит произвольно и прозрачно для приложения изменять представление данных во внешнем хранилище (РСУБД), не модифицируя код приложения. На этой идее базируется трехуровневая архитектура организации хранения данных, которая будет подробней рассмотрена в последней главе. Вопросам же реализации такой системы посвящается статья «Среда ParJava для разработки SPDM-программ для однородных и неоднородных сетей JavaVM». 79
3. Особенности проблемы долговременного хранения информации для ОО программ В данном разделе остановимся на рассмотрении некоторых конкретных деталей организации долговременного хранения информации в объектно-ориентированных программах. Набор концепций и правил, на которых строится ОО приложение, порождает ряд специфических особенностей проблемы хранения информации в ОО системе. Если сравнить исследования, проводившиеся группами, которые разрабатывали различные технологии долговременного хранения информации (ООСУБД, ОРСУБД, CORBA Persistent Object Service, 3-х уровневая архитектура клиент/сервер приложения/РСУБД), то легко увидеть очень много общего, как в самой проблематике этих исследований, так и в подходах к ее разрешению. Попробуем на примере нескольких работ ([19] – [22]) осветить возникающие вопросы и предложенные пути их решения.
3.1 Долговременное хранение объектов. Механизмы сохранения и восстановления состояний объектов. Начнем с терминологии, применяемой для описания функций хранения информации в ОО системах. Общепринятым и распространенным стало понятие хранимости и хранимого объекта или класса (persistency и persistent object (class)) Хранимость – особое свойство объектов, состоящее в том, что объект может сделать "снимок" своего состояния и сохранить его в некотором хранилище (например, ООСУБД), после чего он может закончить свое существование и быть восстановлен в следующем сеансе работы программы. При этом такой объект, обладающий свойством хранимости, называется хранимым. В дальнейшем можно создать другой объект того же класса (или любого родительского класса исходного объекта) и автоматически проинициализировать его атрибуты, используя сохраненное в базе данных состояние [22]. В результате мы получаем возможность хранить состояние объектов дольше, чем время жизни самих объектов, что фактически означает хранение необходимой клиенту информации. При этом, поскольку внутренние структуры данных являются "собственностью" объекта и скрыты от непосредственного доступа извне, хранимый объект должен предоставлять некоторые методы, с помощью которых можно сохранить и восстановить его состояние. Более того, в сохраняемое состояние объекта могут входить не все его внутренние переменные, а лишь некоторые, о чем "знает" только сам объект. [18], [19]. Реализуется эта идея обычно с помощью наследования объектом от некоторого абстрактного класса или интерфейса, содержащего соответствующие методы сохранения, которые могут реализовываться по-разному в объектах разных классов.
80
Альтернативой такой техники сохранения/восстановления состояния объектов могла бы быть некоторая внешняя система, отвечающая за хранимость и имеющая эксклюзивное право доступа к внутренним переменным любого объекта. В такой схеме потенциально можно было бы сохранять/восстанавливать состояние любого объекта. В документе [21] представлено два приема сохранения состояния объекта: реализация хранимым-классом хранимого интерфейса; сохранение объекта извне, когда для каждого типа внутренних данных объекта существует метод, "умеющий" сохранять переменные этого типа. Однако второй подход, более свойственный алгоритмическим программам, нарушает идею инкапсуляции данных со всеми вытекающими отсюда негативными последствиями. По этой причине первая схема организации долговременного хранения в ОО приложениях является общепризнанной. ОО языки поддерживают концепцию уникальной объектной ссылки (OID) идентификатора, которым обладает каждый объект программы. Не вдаваясь в особенности присваивания этой ссылки, отметим, что всякому объекту такой идентификатор присваивается только один раз при его создании и не может изменяться на протяжении всей жизни объекта. Когда состояние объекта сохраняется в базе данных, этому состоянию присваивается уникальный в пространстве всех хранимых состояний идентификатор (отличный от OID объекта) [22]. Будем в дальнейшем называть этот идентификатор POID (Persistent Object ID). Противоположность хранимому объекту – переходный объект (transient object). Следует отметить, что разные авторы вкладывают в это понятие несколько различный смысл. Например, в [19] переходный объект – это объект, который до текущего момента времени не взаимодействовал с базой данных (не сохранялся и не восстанавливался) и существует только в памяти приложения. Однако в этой интерпретации переходный объект может стать хранимым объектом в будущем, если он принадлежит хранимому классу. С точки зрения же авторов [22] переходный объект - это объект, который существует только в памяти и не может стать хранимым. Аналогично, в работе [21] определяется понятие сохраняемой и переходной памяти для хранимых и переходных объектов соответственно.
3.2 Состояние объекта, межобъектные поддержки целостности базы данных
связи.
Проблема
Теперь поговорим о состоянии объекта и поясним, что понимается под сохранением состояния объекта. В общем случае объект может содержать в себе скалярные и векторные переменные элементарных и составных типов данного языка, а также ссылки на другие объекты, векторы объектов и т. д.
81
Безусловно, в состояние объекта входят значения его внутренних переменных, но, очевидно, что и состояния включаемых объектов (объектов, на которые есть ссылки) также определяют состояние нашего объекта. Хотя некоторые авторы склонны называть состоянием объекта набор текущих значений его внутренних переменных, исключая ссылки на объекты. Для того, чтобы охарактеризовать эти ссылки, они определяют понятие зависимостей [22] для данного объекта как набор всех объектов, на которые ссылается наш объект, а также понятие транзитивного замыкания (Transitive closure of dependencies) - набора всех объектов, достижимых из данного объекта по ссылкам на всех уровнях вложенности. Тогда сохранить состояние объекта - означает сохранить лишь его внутренние переменные. Здесь мы близко подходим к проблеме хранения и представления связей в модели классов задачи. В связи с этим возникает следующий ключевой вопрос, – какую часть работы по "поддержке" межклассовых связей должна взять на себя база данных, а какую следует переложить на приложение. От решения этого вопроса во многом зависит функциональность базы данных и логика всех операций обработки данных (update, insert, delete, ...). Поддержка целостности является важной функцией системы хранения информации, независимо от того, какая технология при этом используется (РСУБД, ООСУБД или архитектуры с промежуточным слоем). При этом может обеспечиваться как структурная целостность данных (чтобы в БД не было ссылок на несуществующие объекты или на объекты несоответствующего типа, зацикливание ссылок, и т. д.), так и логическая (аналог концепции правила "rule" или "constraint" в реляционных базах данных), с помощью которых можно гарантировать выполнение некоторых семантических ограничений данной задачи [14]. Например, в [14] описывается схема объектной базы данных, которая на основе схемы классовой модели сама следит за соответствием взаимных ссылок экземпляров классов, в ней хранящихся. Как правило, все ООСУБД берут на себя такую проверку соответствия[21]. Те же принципы предложены в прототипе стандарта ODMG 2.0. По-разному можно решать вопрос внесения изменений в состояние объекта, существующего в окружении связанных с ним объектов. Можно выполнять автоматическое обновление всего этого окружения (в том числе связей) при попытке модификации любого из входящих в нее объектов. Можно считать, что приложение обязано само сохранять состояния связанных объектов оболочки при модификации некоторого из них. Например, в работе [19] "ссылочные объекты" явно подгружаются и обновляются приложением по мере необходимости. В этой модели существуют три вида объектов в ОО приложении, между которыми возможны взаимные переходы в процессе работы: переходный объект, который не взаимодействовал с базой данных и существует только в памяти программы; 82
хранимый объект, который взаимодействовал в некоторой транзакции с базой данных, и в ней хранится некоторое состояние этого объекта. В кэше клиента есть ассоциация между данным объектом и этим состоянием в базе данных; теневой объект (shadow object), "частично" загруженный в память из базы данных, когда некоторый хранимый-объект имеет ссылку на него. Конкретные переменные объекта не загружены в память. Чтобы объект стал хранимым, нужно явно вызвать операцию загрузки его в память. На рис. 1 приведена диаграмма состояний объекта (стрелками обозначены переходы по тем или иным событиям).
Рис. 1. Диаграмма состояний объекта Для упрощения этой задачи многие системы поддерживают понятие кластера (cluster в COOL, group в SOM), в рамках которого отслеживаются все взаимосвязи между объектами[14]. Кластер становится единицей обмена между хранилищем и программой (при записи в базу и при чтении из нее)[21]. Можно определить некоторый оптимальный размер такого кластера, чтобы минимизировать потери на бесполезную перекачку объектов, которые не используются программой в данной транзакции.
83
3.3 Варианты техники доступа к хранимым объектам в базе данных. Поиск нужного состояния, язык запросов Немаловажной проблемой в задаче долговременного хранения данных для ОО систем является вопрос организации доступа к данным со стороны ОО программ. Необходимо продумать эффективную технику нахождения в базе данных нужных состояний объектов, что является особенно актуальным в задачах, требующих обработки больших объемов данных. В реляционной модели для этих целей используется специальный язык запросов SQL, позволяющий формировать разнообразные и разносторонние запросы поиска нужных данных. Что касается ОО баз данных, в них применяются некоторые из следующих механизмов получения нужных объектов[14]: 1. Доступ к хранимым объектам посредством так называемой "точки входа" – некоторого выделенного объекта в БД, имеющего уникальное имя. 2. Доступ по объектной ссылке. Через точку входа можно проинициализировать некоторый объект в памяти, после чего через содержащиеся в нем объектные ссылки можно получить доступ к целой группе других хранимых состояний [21]. Эта техника обращения к объектам, хранящимся в базе данных, применяется в модели "хранимой" и "переходной" памяти ООСУБД ObjectStore. Определение точек входа для конкретного случая входит в задачи программиста, пишущего приложение. 3. Доступ к объекту через уникальный POID состояния (см. пункт 1). 4. Доступ с помощью языка запросов. Стандарт ODMG 2.0. определяет для этих целей специальный язык запросов OQL (Object Query Language). В трехуровневых архитектурах (ОО клиент/Посредник/РСУБД сервер) в промежуточном слое Посредника обычно производится преобразование запросов клиента, сформулированных в объектных терминах клиента, в SQL-запросы к реляционному серверу. Обрисуем на примере одной реализации такой системы ([19]) возможные способы получения из базы данных тех или иных состояний. В работе [19] определяются понятия Proper и Transitive Extent (сегментов) – как набор всех экземпляров данного класса и всех экземпляров данного класса и всех его подклассов соответственно. В процессе работы создается объект класса Extent с методами Proper(String class_name) и All(String class_name), возвращающими Proper и Transitive сегменты класса class_name соответственно. Эти сегменты, в свою очередь, являются объектами, обладающими методом Where (String where_clause), который необходим для того, чтобы отфильтровывать из полученного множества нужные состояния по некоторому критерию. Также имеется специальный метод getTableNameforClass объекта Database, позволяющий получить имя таблицы в реляционной базе данных, в которой хранятся состояния экземпляров данного класса, после чего использовать это имя в методе Where. Также есть возможность писать запросы с объединением таблиц, получая в процессе работы информацию о таблицах, хранящих нужные данные, от Посредника во время работы. 84
4. Трехуровневая архитектура системы долговременного хранения информации для ОО программ. Связь ОО клиента с реляционной базой данных Рассмотрим вопросы реализации трехуровневой системы хранения информации ОО клиент/Посредник/РСУБД, в которой Посредник обеспечивает прозрачное согласование объектно-ориентированной и реляционных парадигм. При этом клиенту кажется, что он работает с объектно-ориентированной БД, а РСУБД в свою очередь получает стандартные SQL-запросы. Одной из наиболее продвинутых и подробно документированных реализаций является трехуровневая архитектура ОО клиент/Посредник/РСУБД - в сервере компании О2-technology под названием JRB (Java Relational Binding) [19]. Ориентированность на три уровня является достаточно общей тенденцией в информационных системах с долговременным хранением информации. И это обусловлено стремлением разграничить две функционально различные части: ОО приложение, решающее специальную задачу своей предметной области, и хранилище информации, в которое обычно стараются заложить такие качества как максимальная эффективность и удобство хранения данных и доступа к ним. Практически в любых моделях таких программных систем существует некое промежуточное звено, предоставляющее адекватный интерфейс той и другой стороне и инкапсулирующее в себе все несоответствия, возникающие на стыке двух подсистем. Будем в дальнейшем называть этот промежуточный компонент трехуровневой архитектуры Посредником.
3.4 Описание одной из реализаций трехуровневой системы Для более четкого понимания трехуровневой архитектуры рассмотрим в качестве примера подробное описание одной из реализаций - систему JRB. В ней Java-приложение, взаимодействуя с Посредником через интерфейс специального пакета COM.unidata.jb.api, может сохранять состояние своих объектов в реляционной базе данных (Oracle, Sybase). Для этого приложению нужно предварительно импортировать в базу данных схему используемых Java-классов с помощью утилит, выполняемых в период разработки программы. В результате чего создаются таблицы для хранения объектов этих классов и генерируются некоторые исходные тексты Java-классов, выполняющих функции сохранения/восстановления объектов этих классов в базе данных. Код клиента должен компилироваться с включением этих классов. В работах [20] и [21] предложены схемы разработки, где не требуется включения никакого внешнего кода в тело приложения, получаемого при импортировании. Сохраненные состояния могут быть восстановлены в объектах соответствующих классов. API JRB включает в себя специальные классы, с помощью которых можно получать то или иное подмножество хранимых состояний объектов 85
данного класса. Методы этих классов позволяют формировать разнообразные критерии выборки в запросах. Сохранение/восстановление объектов, на которые ссылается данный объект, производится явным запросом к Посреднику. При этом поддерживается концепция "частично" загруженных - теневых объектов (shadow objects). Также возможно сохранение в базе данных массивов произвольного типа (в т. ч., массива объектов). Для обработки больших массивов объектов используется специальная техника загрузки их в память, позволяющая сократить накладные расходы на выделение большого объема памяти под теневые элементы этих массивов. На стороне клиента производится кэширование состояний, получаемых из базы данных. Для того чтобы трехуровневая архитектура допускала одновременную работу нескольких приложений, которые принципиально могут обратиться к одному и тому же состоянию в базе данных с запросом на чтение или на запись, необходимо организовать определенную схему разграничения доступа. JRB использует для этих целей классическую концепцию транзакции. По умолчанию, когда приложение открывает базу данных и считывает из нее некоторое состояние, оно работает в режиме read-only. Транзакция открывается методом begin() класса Transaction и может быть завершена вызовом одного из методов: commit(), validate() или abort(). В JRB существует три типа блокировки состояний объектов в базе данных: shared lock, update lock, exclusive lock. При обращении в режиме read-only объекты никак не блокируются. Когда приложение считывает некоторое состояние, на это состояние накладывается shared lock. При этом на одно и то же состояние может быть наложено одновременно несколько блокировок shared lock. Но как только приложение вызывает метод update() или markModify(), на соответствующее состояние накладывается update lock. На всякое состояние может быть наложена только одна блокировка типа update lock. Update lock гарантирует, что после снятия всех прочих блокировок приложение получит exclusive lock и тогда изменение состояния объекта будет зафиксировано в базе данных. Однако наличие update lock еще не исключает возможности возникновения ситуации deadlock. Если приложения заходят в deadlock, они должны через некоторый таймаут снять все блокировки и повторить операции снова через случайное время. Для того чтобы гарантировать невозможность возникновения ситуации deadlock, предусмотрен метод lock(), который сразу пытается получить exclusive lock на данное состояние.
5. Заключение Таким образом, мы рассмотрели проблему организации доступа к РСУБД из объектно-ориентированных программ. В результате было выявлено, что наиболее приемлемой архитектурой, которая могла бы обеспечить корректное разделение 86
двух подходов, является трехуровневая архитектура, которая с одной стороны эмулирует для ОО приложения интерфейс ООСУБД, а с другой стороны взаимодействует с РСУБД через обычный SQL интерфейс. Заметим, что трехуровневая архитектура вызывает активный интерес со стороны различных компаний-разработчиков ПО. В применении к хранению данных в БД можно выделить несколько направлений в реализации трехуровневой архитектуры. В первую очередь это трехуровневая организация JDBC интерфейсов. К этой группе относятся такие продукты, как «Data Broker» производства I-Kinetic, «dbAnyWhere» производства Symantec, «jConnect» производства Sybase и др. Вторая группа представлена реализациями сервиса долговременного хранения в рамках архитектуры CORBA. К ней, например, относится «Persistent Object Manager» компании Secant. И, наконец, к третьей группе можно отнести различные вариации по реализации ODMG интерфейса, которые часто включают поддержку также и других стандартов (CORBA, RMI, UML modeling). Здесь можно отметить «CocoBase» компании THOUGHT и «Enterprise Object Framework» производства NeXT Computing. К комплексным трехуровневым решениям относится также «JaguarCTS» компании Sybase. При этом особенно актуальной становится система, реализующая трехуровневую архитектуру и обеспечивающая решение задач как прямого, так и обратного проектирования прикладных программных систем на основе РСУБД. Литература
13. J. Kleindienst, F. Plasil, P. Tuma. “Implementing CORBA Persistent Service”, TR 117, Charles University Prague, Department of Software Engineering, 1995. 14. "Developing OO Applications for Relational DBMS’s". Cayenne Software Inc. White Paper, 1997-1998 15. “The Secant Persistent Object Manager”. Object Magazine, May 1997. 16. G. Booch «Object-Oriented Design». Behjamin/Cummings Publishing Company, 1992 17. Loomis Mary E. S «Object and Relational Technology: Can they cooperate?» Journal of OO programming, 1992 18. Loomis Mary E. S «Object and SQL: Accessing Relational Databases» Journal of OO programming, 1992 19. Frank M., "Object-Relational Hybrids". DBMS Magazine, 1996 20. Frost Stuart "Modeling for the RDBMS legacy". Object Magazine, Sep 1994 21. G. McFarlay & A. Rudmik "A Critical Review/Technology Assessment ". OODBMS Sep. 1993 22. David Tothwell "Java Object Persistence". Technical Overview, Sep. 1996
1. “Why Use an ODBMS?” POET technical reference. http://www.poet.com/t_oovsre.htm 2. “The Common Object Request Broker: Architecture and Specification”. OMG Document, Revision 2.0, July 1995. 3. “CORBA services: Common Object Service Specification”. OMG Document 95-3-31, 1995. Updated: November 22, 1996. 4. “Persistent Object Service specification”. OMG Document 94-10-7, 1994. 5. "Mapping Objects to Relational Databases". Ambysoft White Paper, Oct. 1997. http://www.ambysoft.com/bibliography.html 6. "Integrating Objects with RDBMS". Gemstone System White Paper Inc.,1998 7. Kyle Brown Bruce G. Whitenack "Crossing Chasms: A Pattern Language for ObjectRDBMS Integration". Knowledge Systems Corp. White Paper. 8. Robert C. Martin "Storing Objects in a Database". Usenet Conference comp.database.object, Jul 1997 9. "Object/Relational Mapping Concepts". ONTOS*Integrator White Paper, http://www.ontos.com/mapcon.htm 10. Kyle Brown Bruce G. Whitenack "Mapping Objects to Tables. A Pattern Language". Knowledge Systems Corp. White Paper. 11. Jan Kleindienst, Frantisek Plasil, Petr Tuma. “Lessons Learned from Implementing the CORBA Persistent Object Service”. OOPSLA’96 conference proceedings, San Jose, California, October 6-10, 1996. 12. Jaromir Adamec, Michael Grof, Jan Kleindienst. “Supporting Interoperability in CORBA via Object Services”. Tech. Report 114. Charles University Prague, Department of Software Engineering, October 1995.
87
88
Вследствие такого разделения, есть возможность использования различных СДХ для одной и той же ООС прозрачным для прикладного программиста образом. Обе указанные подсистемы могут быть созданы по отдельности и связаны через интерфейс СДХ.
Объектно-ориентированное окружение, обеспечивающее доступ к реляционным СУБД*
Разрабатываемая система укладывается в эту общую схему. Заметим, однако, что под ООС часто подразумевается собственно интерфейс, предоставляемый прикладному программисту для использования при написании приложения, а под СДХ – интерфейсы более низкого уровня для связи с ядром ООБД (в нашем случае с РСУБД). В таком аспекте систему можно рассматривать так, как она показана на рис. 1.
В.П. Иванников, С.С. Гайсарян, К.В. Антипин, В.В. Рубанов Аннотация. В статье дается описание объектно-ориентированной (ОО) среды программирования, позволяющей организовать прозрачный доступ к реляционной БД из ОО программы. Дается определение необходимых терминов, описание объектной модели среды, языка построения схем БД и языка запросов, с помощью которого осуществляется поиск и обработка хранимых объектов. Излагаются общее описание алгоритмов работы и этапы разработки целевого ОО приложения. Описанная архитектура базируется на стандарте для объектно-ориентированных СУБД ODMG 2.0 и реализует некоторое его подмножество. На базе изложенного описания будет реализован прототип трехуровневой системы для ОО программирования задач с хранением информации в РСУБД.
1. Введение В статье приводится описание схемы и принципов работы объектноориентированной среды доступа к реляционной СУБД, основанной на стандарте для объектно-ориентированных СУБД – ODMG 2.0. Как правило, всякая ОО СУБД состоит из двух четко выраженных подсистем: объектноориентированной среды (ООС), в которой производится программирование прикладной задачи, и подсистемы, обеспечивающей хранение данных (Сервиса долговременного хранения (СДХ)-Persistency Service). Первая подсистема (ООС) реализуется как библиотека классов, обеспечивающих программисту ОО интерфейс к подсистеме хранения, в который входит базовая функциональность ООСУБД: классы, поддерживающие пользовательские сессии, транзакции, хранение объектов в БД, язык запросов и т. д. Вторая подсистема (СДХ) непосредственно связана с хранением информации и отвечает за представление данных, предоставляя интерфейс, через который классы первой подсистемы могут выполнять все необходимые для хранения объектов операции. *
Работа поддержана грантами РФФИ № 96-07-89591 и № 97-01-00142. 89
Рис. 1. Архитектура системы долговременного хранения объектов. Здесь ООС представлена интерфейсами, описанными в стандарте ODMG 2.0 и реализуется в виде упаковки (package) Java и набора системных утилит. А СДХ, в свою очередь, представлен в нашей системе интерфейсами Java Database Connectivity (JDBC) и реализуется соответствующими драйверами и собственно РСУБД. В данной статье мы остановимся на описании именно ООС, которая будет использоваться при программировании и выполнении ОО приложений. Данная среда, как уже отмечалось, соответствует спецификации интерфейсов, описанной в стандарте ODMG 2.0. Этот стандарт специфицирует объектную модель (OM), которая определяет, каким образом организуется долговременное хранение в ОО приложении. То есть вопросы взаимосвязи и взаимодействия хранимых объектов (Persistent objects -PO), их именования, идентификации и 90
т.д., а также архитектуру классов, с помощью которых приложение организует хранение, выборку, обработку PO. В прототипе системы будут реализованы подмножества объектной модели ODMG, языка определения объектов (ODL) и языка запросов (OQL) в рамках стандарта ODMG 2.0. Указанные подмножества описываются в разделах 2, 3 и 4 соответственно.
2. Объектная модель 2.1 Основные понятия и термины Раздел содержит описание необходимой для дальнейшего изложения терминологии, определяя объектную модель, принятую ODMG в качестве стандарта. Данная модель специфицирует конструкции, которые должны поддерживаться любой ООСУБД: Базовыми примитивами являются объект и литерал. Каждый объект обладает уникальным идентификатором (OID). Литерал не имеет идентификатора. Состояние объекта определяется как совокупность значений его свойств. Свойства делятся на атрибуты и связи. Поведение объекта определяется набором методов этого объекта. Тип объединяет два понятия интерфейса и класса. Интерфейс специфицирует только экземпляров (без описания состояния).
абстрактное
поведение
своих
Класс специфицирует абстрактное поведение и абстрактное состояние своих экземпляров. В БД хранятся объекты, доступ к которым, вообще говоря, может осуществляться из нескольких различных приложений. БД основывается на схеме, написанной на специальном декларативном языке ODL (Object Definition Language). БД содержит экземпляры типов (объекты), описанных в данной схеме. Тип обладает внешней спецификацией и одной или несколькими реализациями. Спецификация определяет внешние характеристики типа, т. е. характеристики, которые видны пользователям этого типа, а именно: атрибуты или переменные состояния (если они есть), значения которых можно получить для каждого экземпляра типа. методы, присущие экземплярам типа. исключения (exceptions), которые могут возникнуть в процессе работы методов типа. 91
Реализация содержит внутренние детали и аспекты механизмов работы экземпляров типа. Реализация включает в себя представление и набор методов. Представление – это структура данных, получаемая из определения абстрактного типа на ODL после отображения в конкретный язык программирования (ODL to program language mapping). Каждому атрибуту абстрактного типа соответствует переменная в его представлении. Методы – это тела операций (процедур), объявленных в спецификации данного типа, написанные с использованием классов, предоставляемых ОО средой. Тип может обладать несколькими реализациями, хотя обычно только одна из них используется в конкретной программе. Разделение спецификации и реализации типа, при которой спецификация описывается независимым от языка программирования образом, обеспечивает прозрачный доступ к объекту в неоднородном компьютерном окружении (соответствующий интерфейс на стороне клиента генерируется специальной утилитой – ODL компилятором). Зависимости между типами в объектной модели (ОМ) представляются двумя видами связей, которые отражают соответственно наследование поведения и наследование состояния.
2.2 Наследование поведения Данному типу наследования соответствует понятие ISA-связи (is–a– relationship) – связи наследования между типами, выражающей обобщение, когда супертип наследует поведение подтипа. Объектная модель поддерживает множественные ISA-связи наследования между интерфейсами. На языке ODL ISA-связи представляются двоеточием: interface interface interface interface
Person{…}; Employee {...}; Professor : Employee {...}, Person {…}; Associate_Professor : Professor {...};
2.3 Наследование состояния ODMG определяет также связь наследования (extends), когда наследуется состояние объекта класса: class Person { attribute string name; attribute Date birthDate; }; class EmployeePerson extends Person : Employee { attribute Date hireDate; 92
attribute Currency payRate; relationship Manager boss inverse Manager::subordinates; }; Extends-связь выражает наследование поведения и состояния типа и не допускает множественное наследование.
2.4 Агрегированные типы Объектная модель ODMG поддерживает различные типы объектов-агрегатов, которые состоят из элементов литеральных или объектных (возможно, агрегированных) типов. В рассматриваемом подмножестве ОМ будут поддерживаться следующие агрегированные типы (t означает тип элементов агрегата): Bag
List Array
Object
Collection
Iterator
Bidirectional iterator
Bag
List
Array
Рис. 2. Структура системы агрегированных типов. Интерфейсы всех этих типов наследуются от типа Collection, который является абстрактным интерфейсом, объединяющим общие характеристики. Семантически Bag является неупорядоченным множеством с возможностью содержания одинаковых элементов. List это упорядоченное множество элементов. Array соответствует обычному понятию массива с возможностью динамического изменения размера. Ниже приведены описания этих агрегированных типов на ODL.
interface Collection : Object { exception InvalidCollectionType; exception ElementNotFound{any element;}; unsigned long cardinality (); boolean is_empty(); boolean is_ordered(); boolean allows_duplicates(); boolean contains_element(in any element); void insert_element(in any element); void remove_element(in any element) raises(ElementNotFound); Iterator create_iterator(in boolean stable); Bidirectionallterator create_bidirectionalIterator (in boolean stable) raises(invalidCollectionType); }; Для доступа к элементам объекта Collection используется механизмы Iterator и BidirectionalIterator, которые определяются следующими интерфейсами: interface Iterator { exception NoMoreElementsO; exception lnvalidCollectionType{}; boolean is_stable(); boolean at_end(); void reset(); any get_element() raises(NoMoreElements); void next_position() raises(NoMoreElements); void replace_element(in any element) raises(lnvalidCollectionType); }; interface Bidirectionallterator : Iterator { boolean at_beginning(); void previous_position() raises(NoMoreElements); }; От интерфейса Collection наследуются более детализированные агрегированные типы: interface Bag : Collection { unsigned long occurrences_of(in any element); Bag create_union(in Bag other_bag); Bag create_intersection(in Bag other_bag); Bag create_difference(in Bag other_bag); }; interface List : Collection { exception lnvalidlndex{unsigned long index};
93
94
void
remove_element_at(in unsigned long index) raises(lnvalidlndex); any retrieve_element_at(in unsigned long index) raises(lnvalidlndex); void replace_element_at(in any element, in unsigned long index) raises(lnvalidlndex); void insert_element_aftef(in any element, in unsigned long index) raises(lnvalidlndex); void insert_element_before(in any element, in unsigned long index) raises(lnvalidlndex); void insert_element_first (in any element); void insert_element_last (in any element); void remove_first_element() raises(ElementNotFound); void remove_last_element() raises(ElementNotFound); any retrieve_first_element() raises(ElementNotFound); any retrieveLast_element() raises(ElementNotFound); List concat(in List otherList); void append(in List otherList);}; interface Array: Collection { exception lnvalidlndex{unsigned long index}; void replace_element_at(in unsigned long index, in any element) raises(lnvalidlndex); void remove_element_at(in unsigned long index) raises(lnvalidlndex); any retrieve_element_at(in unsigned long index) raises(lnvalidlndex); void resize(in unsigned long new_size);};
2.5 Атрибуты Как уже упоминалось выше, состояние объекта определяется набором значений его свойств, подразделяющихся на атрибуты и связи. Атрибуты составляют внутреннее состояние объекта. Они могут быть элементарных и агрегированных литеральных или объектных типов. При этом последние выделяются особо, так как включение одним объектом в свой состав других объектов является типичным для ОО программирования. Они называются атрибутами-ссылками. Реально объекты ссылаются друг на друга посредством своих идентификаторов (объектной ссылки OID или идентификатора 95
хранимого объекта POID), поэтому значение атрибута-ссылки – это объектная ссылка OID некоторого объекта в приложении или POID в БД. При отображении хранимых объектов из БД в приложение идентификаторы хранимых объектов соответствующим образом преобразуются в объектные ссылки. Заметим, что атрибуты являются абстрактным описанием состояния объекта и не обязаны соответствовать структурам данных при отображении в конкретный язык программирования. Они могут реализовываться и как набор соответствующих методов.
2.6 Связи Тогда как свойства-атрибуты объекта характеризуют его внутреннее состояние, свойства-связи используются для задания семантических связей (отличных от связей наследования) с другими типами в спроектированной пользователем Объектной Модели Задачи (ОМЗ). Отметим, что связи – не то же самое, что атрибуты-ссылки. Атрибуты-ссылки характеризуют состояние объекта, которому принадлежат, путем задания ссылки на объекты, входящие в состав данного, и являются однонаправленными (отражают семантику объекта-агрегата), тогда как связи характеризуют не состояние объекта, а участие его в том или ином отношении к другим объектам в смысле семантических связей задачи и всегда являются двунаправленными. Хотя синтаксическая реализация этих свойств в конкретных языках программирования и совпадает. Связи могут существовать между экземплярами только двух типов (которые могут совпадать), т. е. связи являются бинарными. Свойства-связи, также как и атрибуты, объявляются в ODL-схеме БД. В объявление связей входит обязательное указание на обратное направление связи. Ниже приведен пример связи двух классов Professor и Course. interface Professor { relationship set teaches inverse Course:: is_taught_by;}; interface Course { relationship Professor is_taught_by inverse Professor:: teaches; }; Реализуются связи, также как и атрибуты-ссылки, с помощью объектных ссылок (POID и OID) на связанный объект, массива ссылок, либо объектовагрегатов таких ссылок. Связи по типу бывают упорядоченные и неупорядоченные, в зависимости от типа агрегата, представляющего связь. Например, bag – неупорядоченная связь, тогда как list<Member> – упорядоченная. Заметим, что упорядоченные связи практически мало применяются для моделирования реальных прикладных задач. Связи также различаются по мощности (количеству элементов с обеих сторон) и бывают следующих типов: 1:1, 1:n, n:m. 96
Механизм связей ODMG – двунаправленный. При этом СУБД обязана отслеживать корректность взаимных ссылок хранящихся в БД объектов согласно имеющейся схеме и обеспечивать целостность данных, в частности удаление связей на объект со стороны других объектов при его удалении из БД (обеспечение целостности для атрибутов-ссылок не гарантируется). Описанные в формате ODL связи – лишь абстрактная спецификация. Для организации нормальной работы и использования связей необходимо описать некоторые классы и методы, позволяющие устанавливать, видоизменять и удалять эти связи. Так ODL – описание связи (1:1): relationship X inverse Z; преобразуется в эквивалентное IDL – описание: attribute X, Y; void form_Y(in X target); void drop_Y(in X target); Аналогично, для связей мощности 1:n имеем: relationship set<X> Y inverse Z;
быть создан в памяти приложения и проинициализирован состоянием, хранимым в БД. Следует разделить понятия уникального Объектного Идентификатора в прикладной программе (OID) и уникального Объектного Идентификатора Хранимого Объекта в БД (POID). OID и POID представляют, вообще говоря, независимые пространства идентификаторов. При этом один и тот же хранимый объект, имеющий свой постоянный POID в БД, может обладать различными OID в прикладной программе при её запуске в разные моменты времени.
2.9 Сегмент (extent) БД Сегментом объектного типа называется совокупность всех хранимых объектов данного типа в рамках определенной БД. Если тип B наследуется от типа A, то сегмент типа B является подмножеством сегмента типа A. Сегменты имеют большое значение для работы целевого приложения. Они являются той базовой единицей, по которой производятся OQL запросы на получение хранимых в БД объектов. Если провести параллель с реляционной БД, сегменту можно сопоставить реляционную таблицу.
2.10
Объекты с возможностью хранения
Для обработки возникающих в процесс работы ошибок в ODMG применяется модель исключительных ситуаций, аналогичная используемой в C++ и Java. Исключения в ОМ являются объектами и обладают интерфейсом для связи их с другими исключениями и методами, которые могут вызывать или обрабатывать эти исключения.
Все объекты приложения подразделяются на объекты с возможностью хранения (persistent-capable, PC) и объекты без возможности хранения (nonpersistent-capable, NPC), т. е. объекты, которые могут или не могут обладать свойством хранимости (persistency) соответственно. Реально свойство PC обеспечивается наследованием от хранимых классов и интерфейсов, предоставляемых ООС. Для того чтобы объект потенциально мог быть сохранен в БД, он должен быть PC, хотя это не означает, что всякий такой объект с необходимостью будет сохранен по окончании транзакции. В этом отношении пользователю предлагается гибкая схема, когда он может явно указать на необходимость сохранения конкретного PC объекта, либо обозначить все используемые в программе PC объекты как объекты, которые должны быть сохранены. Вследствие агрегирования одними объектами в своем составе других объектов (по объектным ссылкам), операция сохранения некоторого объекта может повлечь за собой необходимость сохранения объектов, на которые ссылается этот объект. В этой ситуации действует правило, что все те объекты, на которые ссылается исходный объект, также должны быть сохранены, и далее по иерархии. Это правило называется хранимостью по достижимости (Persistency by Reachability (PBR)).
2.8 Хранимые объекты(Persistent Objects)
2.11 Именованные хранимые объекты
Для приложения ООС является хранилищем перманентных (хранимых) объектов. При этом в конкретный момент времени такой объект может и не существовать в памяти программы. Но ООС знает уникальный идентификатор (POID) хранимого объекта и знает, как этот объект “синтезировать”, так что по запросу пользователя (т.е. по вызову соответствующих методов ООС) он может 97
98
На IDL: attribute set<X> Y; form_Y (in X target) void raises(lntegrityError); void drop_Y (in X target); void add_Y (in X target) raises(lntegrityError); void remove_Y (in X target); Соответствующие классы, обеспечивающие работу со связями во время выполнения, предоставляются ООС.
2.7 Исключения (exceptions)
Хранимому объекту можно присвоить одно или несколько имен. В приложениях наиболее часто практикуется такая схема работы, когда необходимо получить некоторый начальный объект, используя который, затем можно по объектным ссылкам получить доступ к другим нужным объектам. Имя и является той характеристикой, по которой можно получить начальный
объект из БД. Именованные объекты в БД называются точками входа. Имена являются уникальными в пределах конкретной БД. Именованный хранимый объект можно создать с помощью вызова метода bind(Object object, String name) класса Database, предоставляемого ООС: public class Database { public static Database open (String name, int accessMode) throws ODMGException; public void close() throws ODMGException; public void bind(); public Object lookup(String name) throws ObjectNameNotFoundException; public void unbind(String name) throws ObjectNameNotFoundException; }
тех пор, пока он не обнулится, и тогда объект реально будет удален из БД. Повторное считывание одного и того же объекта из БД предотвращается тем, что ООС будет использовать кэширующую схему, когда каждый хранимый объект, считываемый из БД, будет фиксироваться в специальном буфере системы, и повторные запросы на получение уже считанных объектов будут возвращать OID существующего в памяти объекта.
Кроме того, в классе Database определены методы для получения именованного объекта из БД – lookup(), отключения имени от объекта unbind() и собственно открытия open() и закрытия close() базы данных.
В первом случае метод lookup() создает в памяти приложения объект того класса, которому принадлежит соответствующий именованный хранимый объект в БД и инициализирует его состоянием этого хранимого объекта. Метод lookup() возвращает OID вновь созданного в памяти объекта. Во втором случае создается объект-агрегат, который включает ссылки на множество возвращаемых объектов, которые создаются OQL-запросом в памяти приложения. Описание реализуемого подмножества OQL приводится ниже. Более гибко выглядит схема создания объекта-агрегата, содержащего неразрешенные ссылки на целевые объекты запроса, которые разрешаются по мере того, как пользователь обращается по этим ссылкам. При попытке пользователя обратиться к какому-то объекту по объектной ссылке ООС времени исполнения “подкачивает этот объект” из БД, т. е. реально создает объект в памяти приложения, инициализирует его состоянием соответствующего хранимого объекта и устанавливает значение ссылки в объекте-агрегате, равное ссылке на созданный в памяти объект. Такой подход позволил бы в некоторых случаях сэкономить системные ресурсы, когда не все из запрошенных объектов будут использованы в программе, а также сэкономить время обработки OQL-запроса, асинхронно возвращая управление программе пользователя. С другой стороны, при таком подходе дополнительное время будет тратиться в процессе работы на “подкачку” очередного объекта в программу. Для получения очередного объекта из объекта-агрегата будет использоваться класс-итератор, который и будет активизировать методы, осуществляющие подкачку очередного объекта в память приложения.
2.12 Создание объектов Объекты с возможностью хранения создаются так же, как и обычные объекты приложения, т.е. с помощью вызова конструктора соответствующего класса. При этом по окончании формирования объекта в памяти программы, в БД этого объекта еще не существует. До выполнения первой операции сохранения нового объекта нет никакого объекта в БД, связанного с данным объектом приложения. Когда же была выполнена операция сохранения объекта в БД, ООС реально создает хранимый объект в БД, который в некотором смысле является образом объекта в приложении, и сохраняет в нем текущее состояние нашего объекта. Созданный в БД хранимый объект обладает собственным уникальным идентификатором POID.
2.13 Поддержка целостности БД. Множественные ссылки В объектной модели задачи может реализоваться ситуация, когда на один и тот же объект могут ссылаться несколько других, включающих его в себя, объектов. По этой причине в некоторых операциях с БД (сохранить, считать из БД) могут возникать дублирующиеся операции над одними и теми же объектами при распространении начальных операций по объектным ссылкам (см. ниже описание схем выполнения операций сохранения, удаления объектов). В других операциях (удалить) могут возникать неразрешимые ссылки, когда один из ссылающихся объектов удаляет по ссылке объект из БД, после чего другой уже не может разрешить свою ссылку на удаленный объект. Для устранения этих несоответствий, с каждым объектом в БД и каждым объектом в приложении (для приложения обычно выполняется самой объектной средой) необходимо связать счетчик числа ссылок на этот объект со стороны других объектов. Тогда операция удаления объекта из БД будет уменьшать счетчик ссылок на объект до 99
2.14 Получение хранимых объектов из БД Ранее сохраненные в БД хранимые объекты могут быть получены из БД и отображены в объекты приложения соответствующего класса. Существует два способа получения хранимых объектов из БД: по имени объекта, используя метод lookup() класса Database. с помощью OQL-запроса к БД.
2.15 Сохранение PC объектов в БД Для сохранения некоторого объекта с возможностью хранения в БД, используется хранимый метод этого объекта save(), содержащийся в унаследованном хранимом классе ООС. Операция сохранения PC объекта 100
выглядит единообразно для всех объектов, независимо от того способа, которым он был создан в приложении. Объект мог быть создан ООС с образа ранее существовавшего в БД хранимого объекта (например, с помощью OQL запроса), и тогда метод save() произведет обновление состояния соответствующего хранимого объекта в БД текущим состоянием сохраняемого объекта. Иначе, объект мог быть сконструирован конструктором соответствующего класса, вызванного самой прикладной программой, и тогда метод save() активизирует алгоритм создания нового хранимого объекта в БД и сохранит в нем состояние нашего объекта.
2.16 Удаление хранимых объектов из БД Для удаления некоторых хранимых объектов из БД, необходимо просто указать ООС, какие именно хранимые объекты (по какому признаку) должны быть удалены. Простейшим способом можно удалить хранимый объект, когда в программе существует соответствующий ему образ, ранее созданный из данного хранимого объекта. Между объектами с возможностью хранения приложения и хранимыми объектами БД в каждый момент времени существует взаимно однозначное соответствие (устанавливаемое между OID и POID). Поэтому, для выполнения операции удаления объекта вызывается метод delete (Object o) класса Database, которому передается объект в памяти приложения (Object o). Все объекты, входящие в состав удаляемого объекта , также должны быть удалены, что осуществляется рекурсивно. Все семантические связи с объектами ОМЗ также должны быть удалены с обеих сторон, что выполняется ООС. После удаления из БД хранимого объекта, в памяти еще остается соответствующий ему объект, который как бы “теряет” свой образ в БД, но с которым приложение может продолжать работать. Впоследствии этот объект может опять быть сохранен в БД, и для него будет создан новый хранимый объект (с новым POID), с которым он будет ассоциирован. Класс Database содержит также методы delete( c), которым могут передаваться агрегаты объектов для удаления.
2.17 Пользовательские сессии, транзакции. Сервисы Объектно-ориентированная СУБД, как и всякая другая, поддерживает концепции пользователей, прав доступа к объектам БД, пользовательских сессий и других понятий, обеспечивающих возможности по разделению БД, как общего ресурса. Все вышеперечисленные и прочие возможности могут реализовываться как отдельные сервисы ООС, реализуемые в библиотеках классов, которые предоставляются прикладному программисту для использования в процессе написания программ. Эти сервисы могут быть надстроены на базе основной (core) объектной модели. В первой версии системы данные сервисы не будут реализованы. Они могут быть добавлены на дальнейших этапах разработки. Таким образом, будет реализовываться 101
однопользовательская система хранения объектов, где клиентское и серверное приложения работают на одной и той же машине. Концепция транзакций в базовой версии будет реализована в объеме, специфицированном стандартом ODMG. Методы класса, реализующего транзакции, будут активизировать операции по обмену данными с СДХ, например, вызов метода commit() запустит алгоритм сохранения состояний изменившихся объектов в БД.
3. Язык определения объектов (ODL) ODL – язык, используемый для определения спецификаций объектных типов в соответствии с объектной моделью ODMG. Он предназначен для обеспечения переносимости схем объектных баз данных между различными объектными БД и является аналогом языка определения данных (DDL) в реляционных БД. ODL предполагает определения объектов, которые могут быть реализованы в различных языках программирования, и поэтому не зависит ни от какого конкретного языка. В настоящее время поддерживается преобразование (меппинг) конструкций ODL в C++, Smalltalk и Java. В данном разделе рассматривается базовое подмножество ODL и преобразование типов ОМ ODMG в язык Java. Полное описание ODL можно найти в [1].
3.1 Спецификация ODL 3.1.1 Определение структуры файла ODL Определения ODL делятся в нашем случае на описания исключений, интерфейсов и классов. <specification>
::= <definition> | <definition><specification> <definition> ::= <except_dcl>;| ; | ; ::= | ::= {[]} ::= interface ::= interface [] ::= {} ::= class [extends <scopedName>] [] []
102
Таким образом, файл описаний ODL состоит из набора определений этих объектных типов, которые могут чередоваться в любом порядке. Рассмотрим подробней их характеристики.
::= :<scoped_name>[,] ::= ( [extent_spec][] ) <extent_spec> ::= extent <string> ::= key[s] ::= | , ::= <property_name>|(<property_list>) <property_list> ::= <property_name> | <property_name>, <property_list> <property_name> ::= <scoped_name> ::= < identifier>| :: < identifier> | <scoped_name> ::
В каждом определении класса может быть не более одного описания сегмента и ключа, но при этом самих ключей может быть более одного. Наследование, определяемое extends, задает связь типа extends, а интерфейсы, указываемые после двоеточия, задают связи типа IS-A. Приведем несколько примеров, использующих указанные возможности: interface Student-IF { interface_body } class Postgraduate extends ( extent students key ( name, group) ) { interface_body }
Student: Student-IF
<export>
::= <export> | <export> ::= <except_dcl>;| ; | ;| ;
::= attribute <domain_type> [ ] <domain_type> ::= <simple_type_spec>| <struct_type> | <enum_type> ::= relationship inverse ::= | < > ::= :: ::= <parameter_dcls> [ ] ::= <simple_type_spec> | void <parameter_dcls> ::= ( [<param_dcl_list>] ) <param_dcl_list> ::= <param_dcl> | <param_dcl>, <param_dcl_list> <param_dcl> ::=<param_attribute><simple_type_spec> <declarator> <param_attribute> ::= in | out | inout ::= raises ( <scoped_name_list> ) <scoped_name_list> ::= <scoped_name> | <scoped_name>, <scoped_name_list>
3.2 Пример описания ODL Приведем описание схемы институтской иерархии, которое соответствует графическому представлению, изображенному на рис. 3.
3.1.2 Спецификация тела интерфейса В теле интерфейса или класса определяются атрибуты и операции экземпляров данных типов. Атрибуты делятся на атрибуты-данные и атрибуты-связи. Связи всегда двунаправлены. Если связь указана в одном определении, то она должна быть описана и в определении типа, на который ссылается источник. Описания операций полностью соответствует спецификации OMG IDL. BNF спецификация определяется следующим образом:
103
104
}; // Класс Профессор наследует состояние Служащего class Professor extends Employee ( extent professors ) // сегмент Профессоры { // связь с Секциями (профессор преподает несколько секций) relationship set<Section> teaches inverse Section::is_taught_by;// обратная связь short grant_tenure() // избрать // возможное исключение raises (ineligible_for_tenure); }; // интерфейс Студент interface Student-IF { attribute string name; // ФИО attribute string student_id; // идентификатор // связь с секциями (студент изучает несколько секций) relationship set<Section> takes Inverse Section::is_taken_by; }; // Класс Ассистент наследует состояние Служащего и поведение Студента. class TA extends Employee : Student-IF { // связь с секцией ассистента Relationship Section assist inverse Section::has_TA; attribute string name; // ФИО attribute string student_id; // идентификатор // связь с секциями (ассистент изучает несколько секций) relationship set<Section> takes inverse Section::is_taken_by; };
Рис. 3. Графическое представление схемы ODL. // Класс Зарплата class Salary { attribute float base; // оклад attribute float overtime; attribute float bonus; // Класс Служащий class Employee ( extent employees key id ) { attribute string name; attribute short id; attribute Salary annual_salary; void hire(); void
// сверхурочные // премия};
// сегмент Служащие // ключ ID
// ФИО // идентификатор // зарплата // нанять служащего // уволить служащего fire() raises ( no_such_employee ); 105
3.3 Соответствие типов данных ODL и Java Файл ODL, создаваемый программистом для описания схемы классов приложения в независимой от языка программирования форме, подлежит в конечном итоге трансляции в конструкции конкретного языка. В рамках нашей работы нас интересует преобразование типов из ODL в Java, которое складывается из стандартов ODMG 2.0 и OMG CORBA 2.2. Соответствие между основными конструкциями ODL и Java представлено в таблице. Приведем несколько примеров (названия классов и элементов абстрактные), иллюстрирующих как будет преобразовано описание схемы классов на ODL в конструкции языка Java: 106
ODL Struct Set Bag List Iterator Array Relationship Extent Exception Long Short Unsigned long Unsigned short Float Double Boolean Octet Char String
связаны со схемой БД, созданной в ODL-описании на этапе разработки БД. Имена, фигурирующие в частях , <extent>, , и т. д. – это имена, объявленные в ODL-описании БД. Рассмотрим части OQL-запроса. – имя типа целевого объекта (набора объектов) или итерационной переменной, объявленной в части <extents>.
Java Class public interface Set extends Collection { … } public interface Bag extends Collection { … } public interface List extends Collection { … } Java Enumeration interface Primitive array type[] or Java Vector class Атрибут класса* public interface Extent extends Collection { … }* Java exception int, Integer (class) short, Short (class) long, Long (class) int, Integer (class) float, Float (class) double, Double (class) boolean, Boolean (class) byte, Integer (class) char, Character (class) String
<extents> – сегменты объектов, из которых производится выборка. Это могут быть сегменты, объявленные в ODL-схеме, либо производные сегменты. В этой части запроса могут использоваться итерационные переменные. Ниже на примерах будут продемонстрированы оба случая. – критерий на составляющие части целевого типа, согласно которому производится выборка объектов. AGREGATE_SORT_CRITERIA – часть запроса, содержащая критерии агрегирования (GROUP BY), сортировки (HAVING) и упорядочения результатов запроса (ORDER BY). В нашей работе мы будем реализовывать только часть ORDER BY, имеющую следующий синтаксис: ORDER BY <members> <members> – критерий на составляющие части целевого типа, согласно которому производится упорядочение полученного набора объектов. Таким образом, общий вид OQL запроса в рассматриваемой конфигурации: SELECT FROM <extents> WHERE ORDER BY <members> Результатом запроса может быть упорядоченный или неупорядоченный список объектов ( и соответственно), в котором может содержаться один объект, либо NULL-объект, когда запрос не возвращает объектов.
* не поддерживается стандартом
4. Объектный язык запросов (OQL) Группой ODMG разработан стандарт языка запросов для объектноориентированных баз данных Object Query Language (OQL). Это декларативный язык запросов, базирующийся на языке запросов реляционных баз данных SQL. OQL предназначен для получения объектов, уже хранящихся в БД. Основная конструкция OQL выглядит так же, как и в SQL. Это выражение вида: SELECT FROM <extents> WHERE AGREGATE_SORT_CRITERIA OQL разрабатывался как объектно-ориентированный язык. Результатом запроса является набор объектов (объект-агрегат, содержащий объекты целевого типа). По сложным объектным связям между объектами, атрибутам и методам можно производить навигацию, используя стандартный объектноориентированный синтаксис – оператор “.”. OQL-запросы в программе тесно 107
Теперь рассмотрим подробно возможные виды частей запроса и приведем примеры OQL-запросов, демонстрирующие возможности OQL. В простейшем случае поле <extents> содержит имя сегмента ODL-схемы, а поле содержит имя соответствующего этому сегменту типа в ODLсхеме или имя итерационной переменной, соответствующей этому типу. Напомним, что понятие типа объединяет в себе класс (class) и интерфейс (interface). select p from Persons p; Данный запрос вернет набор всех объектов, принадлежащих сегменту Persons класса Person, объявленному в ODL-схеме. В запросе используется итеративная переменная “p”. В следующем примере демонстрируется случай, когда в поле <extents> фигурирует производный сегмент, содержащий все объекты ”всех объектов”, хранящихся в БД. Заметим, что в этом примере в поле <extents> используется навигация по объектной связи Person -> Child (Children): 108
навигация к методу по типу возвращаемого результата ничем не отличается от навигации к атрибуту, и может использоваться в части и <members> запроса. Когда метод возвращает объект, навигация к методу по типу возвращаемого результата не отличается от навигации по объектной связи, и может использоваться в частях и <extents> запроса. Ниже приводятся примеры
select c from Persons p, p.children c В поле в простейшем случае фигурирует выражение над атрибутами целевого типа: select p from Persons p where p.name = “Jane” Подобно языку SQL можно сформировать запрос с соединением нескольких сегментов (join): select p from Persons p, Flowers f where p.name=f.name Теперь приведем пример запроса с навигацией по объектным связям. В простом случае связи типа 1:1: select p.spouse.address from Persons p В этом примере целевым объектом являются объекты-адреса супругов всех объектов типа “person”, хранящихся в БД. Теперь приведем пример запроса с навигацией по связи типа n:1. Допустим, мы хотим получить объекты-адреса детей всех объектов”, хранимых в БД: select c.address from Persons p, p.children c В этом случае мы фактически строим производный сегмент всех объектов ”всех объектов”, по которому затем производим выборку. Наконец рассмотрим навигацию в запросе типа n:m. Допустим, в нашей объектной модели описаны группы сотрудников такие, что в каждой из них может содержаться много сотрудников и в то же время каждый сотрудник может принадлежать нескольким группам одновременно. Тогда запрос для получения адресов всех сотрудников, принадлежащих всем группам, занимающимся программированием (таких групп много), выглядит так же, как и предыдущий запрос: select m.address from Groups g, g.members m where g.topic = “programming” Однако в этом случае один и тот же объект типа “member” может принадлежать двум или более группам с темой “programming”. Но поскольку реально это один и тот же объект, а каждый объект обладает своим уникальным идентификатором в БД, дублирования в результирующем наборе объектов, который вернет запрос, не будет. В этом смысле объектный запрос всегда работает как “distinct” в SQL. Объектно-ориентированная парадигма распространяется и дальше на язык OQL, и в запросах можно с помощью оператора “.” не только производить навигацию по объектным связям, обращаться к атрибутам объектов, но и вызывать методы объектов. При этом вызываемый метод обязан вернуть значение литерального типа, либо объект. Когда метод возвращает литерал, 109
select x from Students x where x.count_lectures() < 10 В этом примере производится навигация к методу count_lectures() объекта типа “student”, возвращающему численный литерал, который затем используется в критерии запроса. select x from Students x order by x.count_lectures(), x.name В этом примере метод count_lectures() возвращает численный литерал, по которому производится дальнейшее упорядочение результатов запроса. select p.activities().leader from Persons p where p.age < 10 Здесь метод activities класса “person” возвращает объект класса “activity”, а затем производится навигация к объекту класса “person”, связанного с классом “activity”. select a from Persons p, p.activities() a В этом примере все аналогично, только навигация к методу, возвращающему объект, находится в части <extents> запроса, за счет чего создается новый сегмент. Часть , содержащая критерий выборки, в общем случае является объединением нескольких boolean выражений по типу AND или OR. В BNFнотации реализуемого подмножества OQL приводятся все операторы, которые могут быть использованы в критерии. Также допустимы метасимволы в выражениях критерия выборки. В части <members>, содержащей критерий упорядочения, перечисляются через запятую атрибуты целевого типа или методы, возвращающие литерал, по которым нужно упорядочить результат запроса с указанием направления сортировки (ASC – в порядке возрастания, DESC – в порядке убывания). OQL будет реализован как встроенный язык запросов. В OQL-выражении могут использоваться свободные переменные, которые входят в состав абстрактного шаблона OQL-запроса. Перед выполнением такого запроса необходимо связать все свободные переменные с реальными переменными. Для выполнения запросов в программе предусмотрен специальный класс OQLQuery, используемый для формирования запросов, связывания свободных переменных и собственно выполнения запроса: 110
и методы, задаются исключения. Необходимо также создать еще файл конфигурации, в котором описывается определенная служебная информация, в частности типы классов (persistent/transient), способ отметки модификации объектов определенного класса (manual/auto) и т. п.
class OQLQuery { public OQLQuery() {} public OQLQuery(String query) {…} public create(String query) {… } public bind(Object parameter) {… } public Object execute() throws ODMGException {…} } В подмножестве OQL мы не будем реализовывать вложенные запросы.
5. Разработка конечного приложения с использованием системы Опишем общую схему разработки приложений в рамках рассматриваемой системы (см. рис. 4). Отметим действия, предпринимаемые программистом при разработке приложения, и опишем информационные потоки, возникающие в процессе эксплуатации системы.
Рис. 4. Компоненты ОО среды и их взаимодействие. В первую очередь рассматриваем задачу прямого проектирования. На начальном этапе разработки программист создает схему, описывающую классы и связи между ними, используя ODL. При этом в каждом классе определяются атрибуты 111
Далее это описание направляется на вход компилятору ODL, который создает заголовки соответствующих классов на Java. На данном этапе у программиста имеются “шаблоны” интерфейсов и классов его приложения. В описаниях отражены все атрибуты (с типами, соответствующими языковому отображению (language binding)), все операции и исключения, сформированы скелеты конструкторов. То есть делается все, чтобы максимально облегчить механическую работу по набиванию текста. Не хватает только кода, реализующего соответствующие методы и задающего собственно семантику работы (сохранение целостности данных становится задачей ООБД). С точки зрения работы системы данный этап является основным по накоплению начальной информации. В системных файлах создаются описания объектной схемы (1), файлы служебной информации, генерируется реляционное представление объектов (2), а также информация по мэппингу между реляционным и объектным представлением – Dictionary (3), т. е. создаются так называемые метаданные. Теперь программист может использовать сгенерированные описания в своей среде программирования Java и писать приложения привычным для себя образом, используя возможности ООБД путем вызова методов объектов, предоставленных в package RU.ISPRAS.odmg (название предварительное). По завершению определенного этапа разработки, созданные файлы передаются на вход ODMG preprocessor, где к созданным программистом описаниям классов и функций добавляются описания и действия, реализующие собственно работу ООБД. Хотя из-за ограничений на использование препроцессоров в Java, возможен перенос данной нагрузки на ODLCompiler и собственно программиста. Все классы с возможностью хранения модифицируются для наследования интерфейса ODMGObject (название предварительное), в места, где используются или модифицируются хранимые объекты, вставляются вызовы служебных методов fetch() и durty(). Система проверяет правильность использования механизмов долговременного хранения. ODMG preprocessor использует во время своей работы информацию из системного Dictionary и может выдавать сообщения об ошибках. В результате получается набор Java файлов, которые автоматически передаются компилятору javac, который генерирует собственно результат работы – набор class файлов. Далее их можно использовать обычным способом, передавая на Java интерпретатор. Процесс обратного проектирования на этапе работы не отличается от вышеизложенного. Отличие заключается в способе задания соответствия между реляционной и объектной моделями (Dictionary). Если при прямом проектировании представление объектов в РСУБД определяется системой и 112
генерируется на основании ODL описания, то при обратном проектировании это представление уже задано, и нам нужно создать Dictionary на основании специально предоставляемой пользователем информации. А именно, программист сам задает схему РБД и меппинг из объектной модели в реляционную путем описания файлов DDL и MAP. Эти файлы используются программой MapCompiler для преобразования в стандартный формат метаданных. Таким образом, после обработки исходных данных ODLCompiler’ом и MapCompiler’ом, получается тот же набор информации, который используется унифицированным способом. Итак, в архитектуре системы можно выделить следующие компоненты, подлежащие реализации: ODLCompiler (executable) MapCompiler (executable) Preprocessor (executable) JavaAPI package (RU.ISPRAS.odmg) Во время выполнения программы необходимо обеспечить доступ к системным файлам (метаданным), созданным ODLcompiler, так как они активно используются при выполнении функций по записи/чтению из БД. Каждый запрос клиента разбирается Посредником с использованием информации, хранящейся в Dictionary, преобразуется в соответствующий SQL-запрос и поступает в буфер запросов к серверу РСУБД. В Dictionary хранится вся необходимая информация о том, в каких таблицах РСУБД хранятся запрошенные объекты (детали объектов). РСУБД возвращает результат запроса в буфер результатов SQLзапросов Посредника. Получая эту информацию, Посредник начинает строить множество затребованных в OQL-запросе объектов, выделяя под них память и инициализируя объекты информацией, полученной в результате выполнения соответствующего SQL-запроса сервером РСУБД. Сформированные объекты передаются приложению, которое может манипулировать ими как всеми прочими объектами, созданными конструкторами самого приложения, а также применять к этим объектам методы, выполняющие фиксацию изменений в БД, удаление объектов, и т. д. Эти методы активизируют соответствующие действия Посредника по сохранению в РСУБД изменений, удалению информации, и т. д.
ODL и описано отображение конструкций данного языка в Java. Тем самым мы определили все те компоненты (классы и утилиты), с которыми сталкивается прикладной программист в процессе создания приложения, использующего возможности ООБД. И, наконец, в последней главе описана комплексная схема создания приложений, выделены бинарные утилиты (ODLCompiler, MapCompiler, Precompiler) и специфицирован порядок их применения. При этом рассмотрены задачи как прямого, так и обратного проектирования. “Нижний” компонент посредника, как уже отмечалось выше, представлен JDBC интерфейсами, реализуемыми стандартными драйверами. Описание этих интерфейсов можно найти в [13]. Литература 1. R.G.G. Cattell, Douglas K. Barry. “The Object Database Standard: ODMG 2.0”, 1997 2. R.G.G. Cattell. "The Object Database Standard: ODMG-93", 1996 3. “The Common Object Request Broker: Architecture and Specification”, Revision 2.0, July 1995 4. “Persistent Object Service specification”, OMG Document 94-10-7, 1994 5. "ObjectStore API User Guide", "ObjectStore API Advanced User Guide" Release 5.0 ObjectDesign Mar. 1997 http://wwwdb.informatik.unirostock.de/~jo/ostore5/user1/8_schema1.html 6. “The POET Java ODMG Binding”, http://www.poet.com/ 7. “POET Java SDK Programmers Guide”, http://www.poet.com/ 8. David Tothwell “Java Object Persistence”, Technical Overview, Sep. 1996 9. Jan Klendienst, Frantisek Plasil, Petr Juma "Lessons Learned from Implementing the CORBA Persistent Object Service", Charles University 10. James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy, William Lorensen "Object-Oriented Modeling and Design" Prentice Hall, 1991 11. G. Booch "Object-Oriented Design" 1992, Behjamin/Cummings Publishing Company 12. Loomis Mary E. S. "Object Versioning" Journal of OO programming 1992 13. “Java® 2 Platform API Specification”, Sun Microsystems, http://java.sun.com/products/jdk/1.2/docs/api/index.html
6. Заключение В статье был рассмотрен «верхний» компонент Посредника – Объектноориентированная среда. Эта среда связывает приложение с «нижним» уровнем системы – Сервисом долговременного хранения (СДХ). При этом, интерфейсы, предоставляемые приложению, соответствуют стандарту на ООБД ODMG 2.0. Была подробно изложена соответствующая объектная модель, введены основные понятия и термины, объяснены механизмы работы. В качестве средств доступа к хранимым объектам представлены язык запросов OQL и соответствующие классы. Также специфицировано подмножество языка определения объектов 113
114
1.1. Ограниченность адресного пространства
Обеспечение совместимости протоколов IPv4 и IPv6: бесконтекстный IP/ICMP транслятор в среде Linux1
Экспоненциальный рост числа машин, подключенных к сети INTERNET, ведет к быстрому исчерпанию адресного пространства IPv4. Адрес IPv4 имеет длину 32 бита, что дает максимум 4294967296 адресов. Адресное пространство IPv4 не однородно. Существует 5 видов IPv4 адресов: класс A, класс B, класс C, класс D и класс E. Класс А:
В.З.Шнитман, А.А.Ломака Аннотация. В связи с исчерпанием адресного пространства и некоторыми другими проблемами протокола IPv4 возникла необходимость в переходе на протокол следующего поколения IPv6. Однако, поскольку установленная база программного и аппаратного обеспечения IPv4 невероятно велика, возникает проблема обеспечения обратной совместимости. Так же существует проблема развертывания новых сетей, основанных на протоколе IPv6. Имеется несколько возможных механизмов решения этих проблем. В данной статье рассмотрена реализация одного из таких механизмов – механизма бесконтекстной трансляции (Stateless IP/ICMP translator
Класс B: Класс C: Класс D: Класс E:
1. Введение
Рис. 1. Форматы адресов IPv4
Как известно, протокол IPv4 является основой сети INTERNET. Сегодня в мире существуют миллионы машин с установленным стеком протокола IPv4. Однако протокол IPv4 обладает и существенными недостатками, а именно:
ограниченность адресного пространства отсутствие механизма автоматической конфигурации адресов проблема перенумерации машин проблемы, связанные с механизмом фрагментации слабая расширяемость протокола отсутствие поддержки качества обслуживания проблема безопасности коммуникаций
Рассмотрим коротко некоторые из этих недостатков.
1
Любой адрес класса A,B или C глобально идентифицирует один интерфейс в сети INTERNET, либо все интерфейсы некоторой сети (подсети). Адреса класса D (так называемые групповые адреса) используются для идентификации нескольких (т.е. группы) интерфейсов в пределах своей области действия. Адреса класса E зарезервированы и не используются. Таким образом, реальную основу адресации в INTERNET составляют классы A,B и C, т.е. максимум 3758096384 адресов. Эта цифра есть теоретический предел числа хостов в сети INTERNET, в реальности, однако, неэффективность распределения на начальном этапе существенно снизила эту цифру. По расчетам IETF пул глобальных адресов исчерпается примерно в 2005-м – 2011-м году. Следует однако ожидать более быстрого исчерпания адресного пространства в связи появлением и широким распространением портативных устройств, подключенных к глобальным сетям (персональные цифровые помощники, интернет-приставки, электронные записные книжки и т.д.). Стоит также заметить, что применение технологии трансляции адресов (NAT - network address translation) позволяет в некоторых случаях ослабить проблему нехватки адресов.
Данная работа выполнена по гранту РФФИ 99-90220. 115
116
Адресация IPv4 обладает и другим недостатком - слабой агрегацией адресов, что приводит к катастрофичекому росту таблиц маршрутизации в маршрутизаторах сетей, не имеющих маршрута по умолчанию. Такие маршрутизаторы обязаны знать пути ко всем существующим в INTERNET сетям. Известно, что основу распределения адресов сейчас составляют сети класса C, которых может быть максимум 2097152. Таким образом, магистральные маршрутизаторы INTERNET могут потенциально содержать таблицы маршрутизации, состоящие из миллионов записей. Бесперспективность построения таких маршрутизаторов становится очевидной, если заметить, что вся таблица маршрутизации просматривается при обработке каждого пакета. Для решения этой проблемы в настоящее время используются методы бесклассовой междоменной маршрутизации (CIDR – Classless Inter-Domain Routing).
1.2. Отсутствие механизма автоматической конфигурации адресов Изначально, с момента создания, в протокол IPv4 не было заложено механизма автоматического назначения адресов хостам сети (интерфейсам хостов). Эта операция обычно проводится сетевым администратором вручную либо полуавтоматически с использованием таких средств, как протоколы DHCP, RARP или BOOTP. Эта процедура является трудоемкой даже в малых сетях класса С, а в больших сетях вручную попросту невозможна.
1.3. Проблема перенумерации машин С данной проблемой организации сталкиваются при изменении INTERNET провайдера. Она состоит в полном изменении всех IP адресов всех хостов корпоративной сети. При отсутствии механизма автоматического назначения адресов эта перенумерация должна проводится вручную администратором сети. Это черезвычайно трудоемкая операция, учитывая количество машин в современных корпоративных сетях. Для устранения этого недостатка протокола IPv4 был разработан протокол Dynamic Host Configuration Protocol (DHCPv4). Но поскольку это отдельный протокол, не являющийся частью стандарта IPv4, то его реализация имеется далеко не во всех операционных системах, а поэтому не может считаться адекватным решением проблемы управления адресами в сети.
1.4. Проблемы, связанные с механизмом фрагментации Одной из функций протоколов сетевого уровня является фрагментация слишком больших дейтаграмм перед посылкой их к следующему узлу. Дейтаграммы протокола IPv4 могут теоретически достигать размера 65535 байт, в то время как существующие сетевые технологии ограничивают максимальный размер
117
передаваемых пакетов несколькими тысячами байт (типичный пример Ethernet – 1500 байт). Для передачи больших дейтаграмм протокол IPv4 фрагментирует их на несколько более мелких, при этом фрагментацию может осуществлять как отправитель, так и любой маршрутизатор на пути следования дейтаграммы. Возможность (и необходимость) фрагментации дейтаграмм промежуточными маршрутизаторами в IPv4 ограничивает производительность этих маршрутизаторов, так как процедура фрагментации является очень дорогой с точки зрения потребляемых ресурсов маршрутизатора. Фрагментации в промежуточных узлах можно избежать, но для этого отправитель должен определять размер максимального блока передачи данных к конкретному получателю на пути, по которому пойдет пакет (PMTU – Path MTU), и фрагментировать пакет в соответствии с полученным значением PMTU. Для вычисления значения PMTU в протоколе IPv4 существует соответствующий механизм - Path MTU discovery, однако его применение не является обязательным для протокола IPv4.
1.5. Слабая расширяемость протокола В протоколе IPv4 предусмотрен единственный механизм расширения: добавление к заголовку IPv4 дополнительных опций. Однако общая длина всех опций не может превышать 40 байт, что крайне мало в современных условиях.
1.6. Отсутствие поддержки качества обслуживания Со времени создания протокола IPv4 появились новые сетевые приложения, такие как Streaming Audio, Streaming Video и т.д. Для нормальной работы этим приложениям требуется гарантированное обеспечение таких параметров передачи данных, как пропускная способность, задержка и вариация задержки. Набор таких параметров получил название качества услуг. Протокол IPv4 не может обеспечить предоставление гарантированного качества услуг. Для этой цели в заголовке IPv4 служит поле “Type of service”, но ни механизм интерпретации этого поля, ни механизм резервирования необходимых сетевых ресурсов в IPv4 определены не были, поэтому абсолютное большинство существующих маршрутизаторов попросту игнорируют это поле в заголовке IPv4.
1.7. Проблема безопасности коммуникаций Повсеместное распространение компьютерных сетей привело к необходимости разграничения доступа к информации, находящейся в этих сетях. Применительно к протоколам, одним из наиболее удобных мест в семиуровневой модели взаимодействия открытых систем ISO/OSI, в котором можно расположить систему безопасности, является сетевой уровень. К сожалению, в протоколе IPv4 не предусмотрено каких-либо средств организации безопасности передачи данных. 118
Все эти недостатки IPv4 и привели к необходимости разработки IP протокола следующего поколения, который получил название IPv6 или IPng (next generation). В этом протоколе были учтены все недостатки протокола IPv4, а так же были добавлены некоторые новые возможности, повышающие его эффективность и удобство использования. Разработка этого протокола продолжается и по сей день, кроме того для его испытаний в реальных условиях была создана экспериментальная IPv6 сеть 6bone.
Данный обзор не претендует на полноту и не преследует своей целью полностью ознакомить читателя с IPv6. Создатели IPv6 взяли за основу протокол IPv4 и упростили его путем внесения следующих изменений:
был определен механизм создания расширенных заголовков IPv6
все редко используемые возможности протокола IPv4 были вынесены в расширенные заголовки IPv6
был изменен формат адреса, и вообще всей архитектуры адресации. Размер адреса IPv6 был выбран равным 128 битам, чтобы удовлетворить ближайшим и будущим потребностям, даже с учетом существующей неэффективности распределения адресов.
базовый заголовок IPv6 был изменен таким образом, чтобы максимально ускорить его обработку. В частности, все оставшиеся поля были выровнены по своим естественным границам, и из базового заголовка IPv6 была исключена контрольная сумма.
архитектура адресации была создана таким образом, чтобы обеспечить возможность агрегации маршрутной информации. Это необходимо для эффективного функционирования маршрутизации.
была изменена семантика фрагментации 119
был изменен минимально допустимый размер максимального блока передачи данных (MTU)
была исключена возможность широковещания
Базовый заголовок протокола IPv6 имеет следующий вид:
Каким бы привлекательным ни был протокол IPv6, очевидно, что нельзя "за одну ночь" перевести INTERNET на протокол IPv6. Гигантская база разработанного и установленного программного и аппаратного обеспечения IPv4 требует сохранения обратной совместимости IPv6 с IPv4. Такие механизмы совместимости начали разрабатываться одновременно с разработкой самого протокола IPv6. Более того, наличие таких механизмов было одним из критериев выбора среди кандидатов на роль IP протокола следующего поколения. Таких механизмов в IPv6 существует несколько, и данная работа есть реализация одного из таких механизмов.
2. Краткий обзор протокола IPv6
Рис. 2. Базовый заголовок IPv6 Отдельные поля имеют следующее значение: - поле версии протокола, для IPv6 равно 6. Имеет длину 4 Version бита. Traffic class - поле класса трафика; поле определяет уровень качества услуг, который необходимо предоставить при обработке этого пакета. Имеет такое же значение, что и поле Type of service заголовка IPv4. Определение этого поля дается в отдельном документе: "Differenciated services" (RFC 2474). Механизм использования этого поля пока еще находится в стадии разработки. Имеет длину 8 бит.* - метка потока; все пакеты, принадлежащие одному и тому Flow Label же потоку, идентифицируются отправителем одной и той же меткой и обрабатываются промежуточными маршрутизаторами одинаковым образом, т.е. им предоставляется одинаковый уровень качества обслуживания. В данный момент механизм использования этого поля не достаточно определен. Имеет длину 20 бит. - длина полезной нагрузки в октетах, т.е. длина всего пакета Payload кроме самого базового (и только базового) заголовка IPv6. Length Имеет длину 16 бит. Next Header - тип следующего заголовка, им может быть либо один из расширенных заголовков IPv6, либо заголовок протокола верхнего уровня, такой как TCP, UDP и другие. Имеет длину 8 бит. 120
Flags Hop Limit
Source Address Destination Address
- это поле уменьшается на 1 каждым маршрутизатором по пути следования пакета. Пакет сбрасывается, если это поле становится равным нулю. Имеет длину 8 бит. - адрес отправителя. Имеет длину 128 бит.
Fragment Offset
- адрес получателя. Это необязательно адрес конечного получателя. Например, если в пакете есть расширенный заголовок Routing Header, то в этом поле будет находиться адрес следующего узла. Имеет длину 128 бит.
Time to Live
* В самом начале в протоколе IPv6 не было этого поля, потом его ввели, размером 4 бита; затем для унификации с протоколом IPv4 размер поля увеличили до 8 бит, и согласовали его формат с форматом поля “Type of Service” протокола IPv4.
Protocol Header Checksum Source Address Destination Address
Для сравнения ниже приведен формат заголовка IPv4:
Рис. 3. Формат заголовка IPv4
- поле версии протокола, для IPv4 равно 4. Имеет длину 4 бита. - длина заголовка IPv4 в 32-х битных словах. Имеет длину 4 IHL бита. - поле класса трафика; поле определяет уровень качества Type of услуг, который необходимо предоставить при обработке Service этого пакета. Подавляющим большинством маршрутизаторов это поле игнорируется. Определение этого поля дается в отдельном документе: "Differenciated services" (RFC 2474). Имеет длину 8 бит.* Total Length - общая длина пакета в октетах, включая сам заголовок. Имеет длину 16 бит. Identification - уникальный идентификатор, присваеваемый всем фрагментам одного исходного пакета, подвергшегося фрагментации. Используется получателем при сборке исходного пакета по его фрагментам. Имеет длину 16 бит. Version
121
- поле флагов. Содержит флаги DF (don't fragment) - запрет на фрагментацию этого пакета, и MF (more fragments) флаг, указывающий на то, что этот фрагмент является не последним и есть еще фрагменты. - смещение фрагмента в октетах от начала исходного пакета. У всех фрагментов, кроме последнего, поле Fragment Offset должно быть кратно 8. Имеет длину 13 бит. - максимальное время жизни пакета в секундах. Любой промежуточный маршрутизатор обязан уменьшить это поле минимум на 1 независимо от того, сколько времени пакет обрабатывался этим маршрутизатором. Пакет сбрасывается, если это поле становится равным нулю. Имеет длину 8 бит. - тип следующего заголовка, например, TCP, UDP и так далее. Имеет длину 8 бит. - контрольная сумма заголовка IPv4. Имеет длину 16 бит. - адрес отправителя. Имеет длину 32 бита. - адрес получателя. Это адрес необязательно является адресом конечного получателя. Например, если у заголовка есть опция Source routing, то в этом поле будет находиться адрес следующего узла. Имеет длину 32 бит.
* До сих пор не существует стандартизированного способа интерпретации этого поля. В IETF ведется разработка двух архитектур определения качества обслуживания и механизмов его реализации: “Differenciated Services” и “Integrated Services”. Эти архитектуры являются протокольно независимыми, т.е. действуют как на протокол IPv4, так и на протокол IPv6.
Адрес IPv6 имеет длину 128 бит, что дает гигантское адресное пространство. IPv6 адрес, так же как и IPv4 адрес, имеет тип. Тип адреса определяет, что идентифицирует собой этот адрес. Так глобальные unicast адреса идентифицируют одиночные интерфейсы.
Рис 4. Пример глобального unicast IPv6 адреса
122
Этот тип адресов составляет 1/8 общего адресного пространства IPv6. Кроме типа IPv6 адрес имеет еще область действия, она определяет ту часть топологии сети, в которой этот адрес однозначно идентифицирует свой объект. Областью действия может быть:
глобальная сеть INTERNET линк - прямое, немаршрутизируемое соединение хостов, например, сегмент сети Ethernet сайт – сеть, находящаяся под одним административным управлением, т.е. административный домен
Адресное пространство IPv6 настолько большое, что в нем было предусмотрено место для отображения адресных пространств других протоколов, в частности, было предусмотрено место для отображения IPv4 адресов и IPX адресов. Это позволяет разрабатывать механизмы совместимости протокола IPv6 с другими протоколами. Так же, как и в IPv4, все unicast адреса IPv6 состоят из номера хоста, номера сети и префикса типа. Номер хоста имеет длину 64 бита. Поля номера сети и префикса формата имеют переменную длину.
Subnet ID
- номер подсети. Организация, получившая в свое распоряжение отдельный префикс NLA (точнее номер сети), вольна разбить его на несколько подсетей по своему усмотрению. Всего можно организовать до 65535 подсетей с фактически неограниченным числом хостов в каждой из них, так как номер хоста занимает 64 бита.
Эти поля введены в IPv6 для организации агрегации маршрутной информации. Маршрутизация осуществляется с использованием так называемых префиксов. Префикс – это битовая строка, которая побитно сравнивается со старшими битами адреса назначения. Префикс может быть частичным, т.е. иметь длину менее длины адреса IPv6, а может быть полным, т.е. быть адресом IPv6. Маршрутная запись состоит как минимум из поля префикса, адреса следующего узла и поля метрики. Маршрутная таблица состоит из маршрутных записей. При определении исходящего интерфейса для пакета производится поиск префикса максимальной длины, соответствующего адресу назначения пакета. Если совпадение отсутствует, то пакет отсылается по так называемому маршруту по умолчанию (если он есть). Если найдено совпадение, то пакет отсылается по адресу, выбираемому из соответствующей записи таблицы маршрутизации. Путем иерархического построения адреса IPv6 на основе полей TLA и NLA и при соответствующей организации распределения префиксов TLA и NLA можно предотвратить бесконтрольный рост таблиц маршрутизации магистральных маршрутизаторов сети INTERNET.
Локальный на линке IPv6 адрес Локальный на сайте IPv6 адрес Глобальный unicast IPv6 адрес Рис. 5. Unicast адреса Как видно из рисунка, у глобальных IPv6 адресов номер сети структурирован и состоит из следующих полей: - агрегат первого уровня, отдельные TLA могут выдаваться TLA только очень крупным первичным операторам связи INTERNET. Имеет длину 13 бит. - зарезервированное поле. Имеет длину 8 бит. RES - агрегат следующего уровня, этих агрегатов гораздо больше, NLA чем агрегатов TLA. Первичные операторы связи могут выдавать диапазоны идентификаторов NLA вторичным операторам, которые, в свою очередь, могут выдавать отдельные NLA конкретным организациям. Имеет длину 24 бита. 123
В отличие от IPv4, протокол IPv6 имеет встроенные средства назначения адресов хостам (интерфейсам хостов). Такие средства предусматривают регистрацию за хостом одного или нескольких адресов на определенный срок, процедуру "мягкого изъятия" адресов, срок регистрации которых истек, и процедуру продления регистрации адресов. И все это делается без участия человека. Возможно также использование традиционных средств конфигурирования хостов, таких, как протокол DHCP (DHCPv6) и ручное конфигурирование. В IPv6 так же явно выделено понятие маршрутизатора, чего нет в IPv4, благодаря чему конечным хостам не нужно "подсматривать" за протоколами маршрутизации для выполнения автоматической настройки параметров маршрутизации. Протокол IPv6 не имеет средств широковещания. Это важное его свойство способствует повышению эффективности использования полосы пропускания. Типичный пример использования широковещания: протокол ARP – составная часть IPv4. При большом числе подключенных к линку хостов (например,
124
сегмент Ethernet с большим числом подсоединенных хостов) протокол ARP создает так называемые широковещательные штормы, парализующие этот линк. Протокол IPv6 является расширяемым. Кроме базового заголовка IPv6, в пакете могут присутствовать так называемые расширенные заголовки IPv6. Все расширенные заголовки обрабатываются хостами и маршрутизаторами строго последовательно, в том порядке, в каком они встречаются в пакете. Такими расширенными заголовками являются:
routing header (заголовок маршрутизации) - имеет тот же смысл, что и source routing опция заголовка IPv4
destination options - этот заголовок содержит одну или несколько опций и может обрабатываться только получателем пакета
hop-by-hop options - тоже самое, но обрабатывается всеми промежуточными узлами Протокол IPv6 требует, чтобы у всех промежуточных каналов размер максимального блока передачи данных (MTU-maximum transfer unit) был как минимум 1280 байт, что отличается от 576 байт для протокола IPv4. Кроме того, IPv6 отличается от IPv4 в вопросе фрагментации больших пакетов. В IPv4 фрагментацию может производить как отправитель, так и любой промежуточный узел. В IPv6 фрагментацию может производить только хост отправитель, для этого ему нужно знать MTU пути, по которому пойдет пакет. С этой целью специальная процедура - Path MTU discovery - является составной частью протокола IPv6. В протокол IPv6 заложены возможности по организации защищенной передачи данных через сети. Основу этих возможностей составляют расширенные заголовки AH - authentication header, заголовок аутентификации, и ESP encapsulated security payload, заголовок, инкапсулирующий в себе зашифрованный пакет - полезную нагрузку. Способ работы с этими заголовками не является частью самого протокола IPv6, а определяется другими стандартами, такими, как IPsec.
3. Механизмы совместимости IPv6 с IPv4 Существующие подходы к проблеме совместимости IPv6 с IPv4 можно разделить на две категории:
механизмы, обеспечивающие работу наложенных IPv6 сетей поверх существующих IPv4 сетей – эти механизмы обеспечивают взаимодействие IPv6 хостов, используя в качестве среды передачи существующую сеть IPv4 механизмы, обеспечивающие взаимодействие IPv6 и IPv4 хостов
125
К первой категории относятся механизмы туннелирования, а среди механизмов, относящихся ко второй категории, следует отметить двойной стек, шлюз прикладного уровня и IP/ICMP трансляцию. Существует несколько расширений механизма туннелирования и механизма трансляции заголовков, призванные упростить их использование, но эти расширения не меняют семантики соответствующего механизма. Опишем вкратце эти технологии. Двойной стек - в этом случае на каждом IPv6 хосте, которому требуется взаимодействие с IPv4 хостами, устанавливается стек протокола IPv4 и ему выделяется IPv4 адрес. После этого этот хост может взаимодействовать как с IPv4 хостами, так и с IPv6 хостами. Данный метод является самым простым и самым радикальным методом решения проблемы совместимости, однако обладает некоторыми недостатками. Во-первых, он требует установки дополнительного программного обеспечения и его конфигурирования на каждом хосте, что выливается в дополнительную работу сетевому администратору и в повышенные требования к ресурсам хостов. Во-вторых, он требует, чтобы все промежуточные маршрутизаторы могли работать как с протоколом IPv4, так и с протоколом IPv6. Другим существенным недостатком такого "чистого" решения проблемы совместимости является необходимость переписывания всего парка прикладного программного обеспечения для того, чтобы оно смогло работать поверх протокола IPv6. Не стоит и говорить даже о том, что такая задача потребует огромного количества времени и усилий. Шлюз прикладного уровня (ALG - application level gateway) - данный метод предполагает, что для каждого используемого сетевого приложения создается специальное прикладное программное обеспечение, осуществляющее преобразование трафика этого сетевого приложения из трафика IPv4 в трафик IPv6, и наоборот. Недостатки этого метода очевидны: сколько существует сетевых приложений, столько же необходимо создать соответствующих ALG-шлюзов. Следует, однако, заметить, что при организации взаимодействия IPv4 и IPv6 сетей полностью избежать построения ALG-шлюзов, вероятно, не удастся, например, в случае использования службы доменных имен. Туннелирование - данный метод предназначен для создания IPv6 туннелей сквозь существующие IPv4 сети (в частности INTERNET), не поддерживающие протокол IPv6. Такие туннели создаются вручную либо автоматически различными способами и объединяют отдельные IPv6 сети между собой. Пакеты IPv6, входя в такой туннель, инкапсулируются в пакеты IPv4 и пересылаются по IPv4 сети на другой конец туннеля. Там они деинкапсулируются и обрабатываются далее как обычные IPv6 пакеты. На основе таких туннелей, в частности, построена экспериментальная глобальная IPv6 сеть 6bone. Данное решение проблемы совместимости является частичным, оно обеспечивает создание наложенных IPv6 сетей поверх существующей сетевой инфраструктуры. Оно не обеспечивает взаимодействия IPv4 хостов с IPv6 хостами. В настоящий момент именно этот 126
механизм получил наибольшую поддержку среди разработчиков и пользователей в основном потому, что он является основой построения экспериментальной сети 6bone. IP/ICMP трансляция может быть реализована двумя основными методами: контекстным и бесконтекстным. Механизм бесконтекстной IP/ICMP трансляции предполагает установку на границе IPv6 сети специального агента, осуществляющего трансляцию протоколов. При этом IPv6 хостам присваиваются специальные, так называемые IPv4-транслированные, адреса. Приходящие извне IPv4 пакеты перенаправляются этому агенту, проходя который, они подвергаются преобразованию к формату протокола IPv6 и пересылаются далее к своим получателям. Ответные пакеты, идущие от IPv6 хостов к IPv4 хостам (это индицируется специальным типом IPv6 адреса назначения), так же должны пройти через IP/ICMP транслятор, но необязательно через тот же самый, так как сам транслятор является бесконтекстным. Пройдя транслятор, IPv6 пакеты становятся IPv4 пакетами и доставляются по назначению. Удобством этой схемы является ее прозрачность для взаимодействующих хостов и полная бесконтекстность, что существенно облегчает ее реализацию и использование. Данный механизм является относительно новым. При использовании контекстного метода трансляции адресов каждому IPv4 адресу, который может участвовать в процессе трансляции, т.е. каждому возможному IPv4 адресу назначения и каждому возможному IPv4 адресу отправителя, ставится в соответствие некоторый IPv6 адрес. Такая схема позволяет использовать “настоящие” IPv6 адреса, например, те, которые хосты получают в процессе автоматической конфигурации адресов. Однако за такое удобство приходится платить ограничением в числе IPv4 хостов, с которыми возможно взаимодействие. Действительно, каждому IPv4 хосту, с которым потенциально необходимо взаимодействовать, нужно выделить некоторый IPv6 адрес, который будет идентифицировать этот IPv4 хост в IPv6 части сети. Если таких IPv4 хостов мало, то это сделать нетрудно. Однако, если, например, потенциально возможно взаимодействие с любым хостом сети INTERNET, то такое отображение создать просто невозможно. Использование нормальных, а не специальных IPv6 адресов, приводит так же к необходимости подвергать трансляции заголовок транспортного уровня. Действительно, протоколы верхних уровней, например, TCP и UDP, используют псевдозаголовок IP при вычислении своих контрольных сумм. Специальные адреса IPv6 подобраны таким образом, что не меняют значение контрольной суммы при трансляции, в то время как нормальные IPv6 адреса таким свойством не обладают. Поэтому при построении контекстного транслятора необходимо корректировать значения контрольных сумм в транспортных заголовках. Такая схема имеет и побочный эффект: транслятор становится не способным работать с любыми транспортными протоколами, кроме TCP и UDP. Применение механизма бесконтекстной трансляции позволяет избежать такой зависимости. 127
Ниже приведено детальное описание работы бесконтекстного транслятора, за которым следует описание его реализации.
IP/ICMP
4. Бесконтекстный межпротокольный IP/ICMP транслятор Межпротокольный транслятор работает на сетевом уровне семиуровневой модели взаимодействия открытых систем OSI/ISO и осуществляет преобразование заголовков IPv6<->IPv4, не изменяя при этом заголовков и данных протоколов вышестоящих уровней (за исключением протокола ICMP).
4.1. Область применимости Предполагается, что механизм межпротокольной трансляции будет использован на раннем этапе перехода к протоколу IPv6, а в дальнейшем его применение будет ограничено. Схема IP/ICMP трансляции является односторонней в том смысле, что она предназначена для интеграции IPv6 сетей с IPv4 Internet, а не наоборот. Это выражается в требовании выделения IPv6 хостам IPv4 адресов (точнее IPv4-транслированных IPv6 адресов, полученных на основе выделенных IPv4 адресов). Действительно, для того, чтобы IPv6 хост мог послать пакет IPv4 хосту, ему необходим его IPv6 адрес, который он пропишет в поле Destination Address пакета IPv6. Аналогично, для того чтобы послать пакет, IPv4 хосту необходим IPv4 адрес назначения (destination address). Для этих целей механизм бесконтекстной трансляции требует выделения диапазона IPv4 адресов (т.е. подсети) IPv6 хостам и выделения из этого диапазона каждому IPv6 хосту IPv4 адреса. В дальнейшем, когда будут преобладать IPv6 сети, необходимость в бесконтекстной IP/ICMP трансляции отпадет, и, возможно, встанет проблема совместимости оставшихся IPv4 сетей с IPv6 сетями. Для этой цели схема бесконтекстной IP/ICMP трансляции не подходит, так как иначе пришлось бы присваивать IPv4 адреса удаленным IPv6 хостам, в том числе и находящимся под другим административным управлением. Свойство односторонности механизма трансляции проистекает из такого фундаментального факта, как различная емкость адресных пространств у протоколов IPv6 и IPv4. Действительно, адрес IPv6 имеет 128 бит, в то время как адрес IPv4 имеет только 32 бита. Это различие приводит к невозможности взаимно однозначного отображения адресных пространств этих протоколов. Отобразить 32 битный адрес IPv4 в 128 битный адрес IPv6 можно, а вот сделать наоборот нельзя. Именно в силу этого факта транслятор может быть использован для организации взаимодействия локальной сети IPv6 (т.е. ограниченного числа хостов, находящихся под одним административным управлением) с IPv4 Internet, и не может быть использован для организации взаимодействия локальной IPv4 сети с IPv6 Internet. 128
Механизм межпротокольной трансляции предполагает, что транслятор находится на границе сетей IPv4 и IPv6 так, как это показано на рисунке:
заголовков протоколов верхних уровней, используются IPv6 адреса специальных типов, причем такие, которые не влияют на значение контрольной суммы. При трансляции используются следующие специальные виды IPv6 адресов:
IPv6 хосты должны иметь IPv4-транслированный IPv6 адрес. Этот адрес соответствует префиксу ::FFFF:0:0:0/96, т.е. старшие 96 бит этого адреса таковы: 0000:0000:0000:0000:FFFF:0000. Младшие 32 бита адреса содержат IPv4 адрес, присвоенный хосту:
IPv4-отображенный IPv6 адрес используется IPv6 хостами для посылки пакетов IPv4 хостам. Старшие 96 бит этого адреса содержат префикс 0000:0000:0000:0000:0000:FFFF, младшие 32 бита адреса содержат IPv4 адрес хоста, для которого предназначен пакет:
Рис. 6. Модель предполагаемой конфигурации сети
Рис. 7. Формат IPv4-транслированного IPv6 адреса
Весь подлежащий трансляции трафик должен проходить через IP/ICMP транслятор. Транслятор называется бесконтекстным потому, что в процедуре трансляции не используется никакой сохраненной ранее информации. Транслятор получает на входе пакет, проверяет, удовлетворяет ли этот пакет критериям трансляции, и затем конвертирует его, используя при этом только ту информацию, которая содержится в самом пакете. При необходимости между IPv4 и IPv6 сетями можно установить более одного транслятора, и это никак не скажется на корректности функционирования схемы трансляции. В отличие от бесконтекстного транслятора, контекстный транслятор осуществляет преобразование адресов пакетов на основании заранее предопределенной таблицы соответствия адресов. Такая таблица содержит соответствие "IPv6 адрес – IPv4 адрес" и должна создаваться вручную. При наличии в сети более одного транслятора необходимо, чтобы их таблицы соответствия были согласованными. Вместо этого, путем использования специальных IPv6 адресов, схема бесконтекстной IP/ICMP трансляции позволяет организовать взаимодействие без необходимости создания таблиц контекстов.
4.2. Адреса, используемые при трансляции Протоколы верхних уровней, такие, как TCP и UDP, для защиты данных от искажения используют контрольные суммы, которые вычисляют на основании данных пакета, своего заголовка и псевдозаголовка протокола нижележащего уровня, т.е. IPv4 или IPv6. В этот псевдозаголовок входят адреса отправителя, получателя, идентификатор протокола верхнего уровня и размер блока данных этого протокола верхнего уровня. Последние два значения не изменяются при трансляции. При трансляции изменяются только адреса. Для того, чтобы при трансляции избежать необходимости пересчитывать контрольные суммы 129
Рис 8. Формат IPv4-отображенного IPv6 адреса
4.3. Маршрутизация в модели предполагаемой сети Как было сказано выше, транслятор должен располагаться на границе IPv4 и IPv6 сетей. IPv6 хостам, для которых требуется возможность взаимодействия с IPv4 хостами, должны быть присвоены IPv4-транслированные адреса. Вопросы присвоения таких адресов IPv6 хостам, а так же установления соответствующей маршрутизации не определяются самой технологией трансляции. Весь трафик, подлежащий трансляции, должен проходить через IP/ICMP транслятор. Для этого необходимо, чтобы в IPv4 сети пакеты, идущие по IPv4 адресам, выделенным IPv6 хостам, пересылались на IP/ICMP транслятор, а в IPv6 сети на IP/ICMP транслятор попадали пакеты, идущие по IPv4-отображенным IPv6 адресам.
130
4.4. Трансляция пакетов протокола IPv4 в формат IPv6 4.4.1. Общая схема
M flag:
При приходе нормального, нефрагментированного пакета IPv4, его данные копируются без изменения, а новый IPv6 заголовок строится следующим образом: 6 Version: Копируется из поля “Type of Service” заголовка Traffic Class: IPv4 0 (все нули) Flow Label: Значение поля “Total Length” заголовка IPv4 Payload Length: минус размер самого заголовка и IPv4 опциий, если они присутствуют Копируется из поля “Protocol” заголовка IPv4 Next Header: Значение поля “TTL” плюс 1, так как пакет Hop Limit: проходит через два стека: сначала стек IP6, затем стек IPv4 (или наоборот, см. описание реализации) В младшие 32 бита копируется IPv4 source Source Address: address, в старшие 96 бита копируется префикс: 0000:0000:0000:0000:0000:FFFF В младшие 32 бита копируется IPv4 destination Destination Address: address, в старшие 96 бита копируется префикс: 0000:0000:0000:0000:FFFF:0000
Identification:
4.4.3. Трансляция информационных сообщений ICMPv4 Из всех возможных информационных ICMPv4 сообщений трансляции подлежат только сообщения Echo и Echo Reply. Они транслируются в ICMPv6 сообщения Echo Request и Echo Reply, соответственно. При трансляции так же пересчитывается поле контрольной суммы, в вычисление которого включается псевдозаголовок IPv6. Данные пакета копируются без изменений.
4.4.4. Трансляция сообщений ICMPv4 об ошибках Любое ICMPv4 сообщение об ошибке содержит в себе пакет, вызвавший ошибку (точнее столько байт этого пакета, чтобы суммарная длина пакета сообщения об ошибке не превышала 576 байт). Поэтому необходимо транслировать не только сам заголовок ICMPv4, но и пакет, вызвавший ошибку, т.е. производить рекурсивную трансляцию. Трансляция заголовка ICMPv4 происходит по следующей схеме:
Destinaton Unreachable (Type 3): если не определено иначе, поле Type выставляется равным 1 Code 0 и 1: выставить поле Code равным 0 (no route to destination)
Если в пакете присутствуют IPv4 опции, то они игнорируются.
Code 2: транслировать в сообщение ICMPv6 Parameter Problem (Type 4, Code 1), в котором выставить поле Pointer на IPv6 поле Next Header
4.4.2. Обработка фрагментов Если в пакете сброшен флаг DF (don't fragment), либо пакет является фрагментом, то при трансляции к базовому заголовку IPv6 необходимо добавить расширенный заголовок Fragment Header. Поля выставляются так, как описано выше, за следующим исключением: IPv6 заголовок: Payload Length: Next Header: Fragment Header: Next Header: Fragment Offset:
Копируется флаг “More Fragments” заголовка IPv4 Копируются младшие 16 бит поля “Identification” заголовка IPv4
Code 3: выставить unreachable)
поле
Code
равным
4
(port
Code 4: транслировать в сообщение ICMPv6 Packet Too Big (Type 2) c Code равным 0. Поле MTU необходимо скорректировать на разницу между размером заголовка IPv4 и IPv6
“Total length” заголовка IPv4 плюс 8, минус размер IPv4 заголовка с опциями 44 (fragment header)
Code 5: выставить поле Code равным 2 (not a neighbor)
Копируется из поля “Protocol” заголовка IPv4 Копируется из поля “Fragment Offset” заголовка IPv4
Code 6 и 7: выставить поле Code равным 0 (no route to destination) 131
132
Code 8: выставить поле Code равным 0 (no route to destination) Code 9 и 10: выставить поле Code равным 1 (communication with destination administratively prohibited) Code 11 и 12: выставить поле Code равным 0 (no route to destination)
Time Exceeded (Type 11): выставить поле Type равным 3, поле Code остается без изменения
Parameter Problem (Type 12): выставить поле Type равным 4. Поле Pointer должно указывать на соответствующее поле в транслированном IP заголовке Все остальные сообщения об ошибках должны просто сбрасываться.
4.5. Трансляция пакетов протокола IPv6 в формат IPv4
Header Checksum: Source Address:
Destination Address:
Если в пакете присутствуют расширенные заголовки, то они просто игнорируются.
4.5.2. Обработка заголовка фрагментации При наличии в исходном IPv6 пакете заголовка фрагментации IPv4 заголовок строится так, как показано выше, за следующим исключением: Total Length:
Identification:
4.5.1. Общая схема
Flags:
При приходе пакета IPv6, не содержащего заголовка фрагментации, его данные копируются без изменения, а новый IPv6 заголовок строится следующим образом: 4 Version: 5 Internet Header Length: Копируется из поля “Traffic Class” заголовка Type of Service and IPv6 Precedence: Значение поля “Payload Length” заголовка Total Length: IPv6, плюс размер IPv4 заголовка 0 Identification: MF выставляется в 0, DF выставляется в 1 Flags: 0 Fragment Offset: Значение поля “Hop Limit” плюс 1, так как Time to Live: пакет проходит через два стека: сначала стек IP6, затем стек IPv4 (или наоборот, см. описание реализации) Значение поля “Next Header” заголовка IPv6 Protocol:
Fragment Offset:
133
Пересчитывается после заполнения остальных полей Если IPv6 Source address есть IPv4транслированный IPv6 адрес, то из него копируются младшие 32 бита, иначе это поле выставляется равным 127.0.0.1 Копируются младшие 32 бита IPv6 адреса назначения
Protocol:
Значение поля “Payload Length” заголовка IPv6 минуc размер заголовка Fragment Header, плюс размер заголовка IPv4 Копируются младшие 16 бит поля “Identification” заголовка Fragment Header DF выставляется в 0, MF копируется из флага M заголовка Fragment Header Копируется из поля “Fragment Offset” заголовка Fragment Header Копируется из поля “Next Header” заголовка Fragment Header
4.5.3. Трансляция информационных сообщений ICMPv6 Из всех возможных информационных сообщений ICMPv6 трансляции подлежат только сообщения Echo Request и Echo Reply. Они транслируются в ICMPv4 сообщения Echo и Echo Reply, соответственно. При трансляции также пересчитывается поле контрольной суммы. Данные пакета копируются без изменений.
4.5.4. Трансляция сообщений ICMPv6 об ошибках Так же, как и в протоколе ICMPv4, любое ICMPv6 сообщение об ошибке содержит в себе пакет, вызвавший ошибку (точнее столько байт этого пакета, чтобы суммарная длина пакета сообщения об ошибке не превышала 1280 байт). Поэтому необходимо транслировать не только сам заголовок ICMPv6, но и пакет, вызвавший ошибку, т.е. производить рекурсивную трансляцию. Трансляция заголовка ICMPv6 происходит по следующей схеме: 134
пересылать блоки данных размером большим либо равным 576 октетам. У протокола IPv6 минимальное значение MTU было повышено до 1280 октетов.
Destination Unreachable (Type 1): Выставить поле Type в 3, а поле Code транслировать следующим образом: Code 0: выставить Code в 1 (host unreachable) Code 1: выставить Code в 10 (communication with destination host administratively prohibited) Code 2: выставить Code в 5 (source route failed) Code 3: выставить Code в 1 (host unreachable) Code 4: выставить Code в 3 (port unreachable)
4.6.2. Наличие в протоколе IPv6 расширенных заголовков
Packet Too Big (Type 2): Транслировать в сообщение ICMPv4 Destination Unreachable c Сode 4. Поле MTU необходимо скорректировать на разницу между размером заголовка IPv4 и размером заголовка IPv6 с учетом наличия в пакете расширенных заголовков.
Time Exceeded (Type 3):
Hop by hop options – опции, обрабатываемые каждым промежуточным маршрутизатором по пути движения пакета Destination options – опции, обрабатываемые только получателем пакета Routing Header – заголовок маршрутизации
4.6.3. Различие в механизме фрагментации
Выставить поле Type в 11, поле Code не изменять.
Parameter Problem (Type 4): Если Code есть 1, то транслировать в сообщение Port unreachable (Type 3, Code 2). Иначе выставить поле Type в 12, а поле Code в 0. Поле Pointer должно указывать на поле, вызвавшее ошибку в исходном пакете. Все остальные сообщения об ошибке необходимо молча сбрасывать.
4.6. Особенности работы транслятора Протоколы IPv6 и IPv4 во многом похожи, но между ними, кроме чисто синтаксических различий, есть и семантические, которые усложняют задачу трансляции. Такими семантическими различиями являются:
В отличие от протокола IPv4, в протоколе IPv6 в основной заголовок входит только базовая информация о пакете. Вся дополнительная информация содержится в расширенных заголовках IPv6. Таких заголовков существует несколько, и, кроме того, могут появляться новые заголовки. Транслятор использует только один такой расширенный заголовок: Fragment Header – заголовок фрагментации. Все остальные расширенные заголовки, имеющиеся в пакете, транслятор обязан игнорировать (те, которые он понимает). Проект стандарта обязывает каждую реализацию знать (и игнорировать) как минимум следующие заголовки:
различие в минимально допустимом размере MTU наличие в протоколе IPv6 расширенных заголовков различие в механизме фрагментации различие в механизме вычисления контрольной суммы протокола ICMP
Как уже отмечалось, одной из функций протоколов сетевого уровня является фрагментация слишком больших дейтаграмм перед посылкой к следующему узлу. Протоколы IPv6 и IPv4 осуществляют эту функцию по-разному. Напомним, что для вычисления значения PMTU в протоколе IPv4 существует соответствующий механизм - Path MTU discovery, однако его применение не является обязательным для протокола IPv4. В протоколе IPv6 было решено избавиться от возможности фрагментации дейтаграмм промежуточными маршрутизаторами, поскольку процедура фрагментации является достаточно дорогой с точки зрения потребляемых ресурсов. Вместо этого, в IPv6 было решено сделать процедуру определения PMTU обязательной. Таким образом, потенциально через транслятор могут взаимодействовать IPv6 хост, осуществляющий определение PMTU, и хост IPv4, не осуществляющий процедуру определения PMTU. При этом транслятор должен:
4.6.1. Различие в минимально допустимом размере MTU Протокол IPv4 не может работать на линиях, у которых максимальный блок передачи данных меньше 576 октетов. Точнее говоря, он не может работать на линиях, у которых нижележащий уровень сетевого интерфейса не может 135
поддерживать механизм определения PMTU со стороны IPv6 осуществлять при необходимости фрагментацию входящих дейтаграмм со стороны IPv4 Поддержка механизма определения PMTU со стороны IPv6 осуществляется следующим образом. При приходе нефрагментированного (т.е. не содержащего заголовка Fragment Header) IPv6 пакета транслятор конвертирует
136
его в пакет IPv4, в заголовке которого выставляет флаг DF (don’t fragment – не фрагментировать). Таким образом, если размер пакета был больше, чем PMTU в IPv4 части сети, то, дойдя до “узкого горла”, пакет будет сброшен, и соответствующее уведомление (с новым значением PMTU) будет выслано посредством протокола ICMPv4. Транслятор, преобразовав это сообщение в ICMPv6 и переслав его получателю, завершит таким образом процедуру определения PMTU со стороны IPv6. Примечание: если окажется, что значение PMTU, полученное в IPv4 части сети, меньше, чем минимальное значение MTU для протокола IPv6, то в этом случае протокол IPv6 обязует отправителя высылать пакеты с размером равным минимальному значению MTU протокола IPv6, но при этом добавлять к пакету заголовок Fragment Header. При приходе пакета IPv6, в котором есть заголовок Fragment Header, транслятор конвертирует его в пакет IPv4 со сброшенным флагом DF, позволяя, таким образом, промежуточным IPv4 маршрутизаторам фрагментировать этот пакет в случае необходимости. При приходе пакета IPv4 с выставленным флагом DF (наличие у пакета выставленного флага DF означает, что отправитель этого пакета поддерживает механизм определения PMTU) транслятор конвертирует его в пакет IPv6, не содержащий заголовка фрагментации Fragment Header. Если размер этого пакета был больше, чем PMTU в IPv6 части сети, то, дойдя до “узкого горла”, пакет будет сброшен маршрутизатором IPv6, и соответствующее уведомление будет выслано с новым значением PMTU. После конвертирования этого сообщения на трансляторе и доставки его отправителю, тот сможет вычислить это новое значение PMTU. По отношению к фрагментации пакетов IPv4 транслятор может вести себя следующим образом: фрагментировать (если это необходимо) пакет до размера PMTU, т.е. поддерживать механизм определения PMTU протокола IPv6 фрагментировать (если это необходимо) пакет до размера минимального значения PMTU протокола IPv6 Необходимость во фрагментации может возникнуть, если входящий пакет IPv4 содержит сброшенный флаг DF, либо если пакет уже является фрагментом. В обоих случаях (даже если фрагментация не производилась) транслятор обязан добавить к пакету заголовок фрагментации Fragment Header.
4.6.4. Различие в механизме вычисления контрольной суммы протокола ICMP Как протокол ICMPv4, так и протокол ICMPv6 содержит в своем заголовке поле контрольной суммы пакета. Однако механизм вычисления этого поля для
137
этих протоколов различается: протокол ICMPv6 при вычислении использует псевдозаголовок IPv6, в то время как ICMPv4 не использует псевдозаголовка IPv4, поэтому при трансляции пакета ICMP любой версии необходимо заново пересчитывать поле контрольной суммы.
5. Реализация Предлагаемая реализация механизма бесконтекстной IP/ICMP трансляции выполнена в виде загружаемого модуля ядра операционной системы Linux. Этот модуль в момент загрузки регистрирует себя в ядре в качестве драйвера дополнительного (псевдо)сетевого интерфейса с именем "siit". Для функционирования схемы трансляции в системе должен существовать еще, по крайней мере, один сетевой интерфейс. Таким образом, после загрузки модуля трансляции в системе будет существовать как минимум два сетевых интерфейса. На представленном ниже рисунке показан пример подключения транслятора:
Рис. 9. Место транслятора в топологии сети В этом примере локальная IPv6 подсеть подключена к Internet через транслятор. Этой подсети выделен диапазон IPv4 адресов 192.168.0.0/16, т.е. сеть класса B. При этом в IPv6 подсети хосты имеют адреса вида ::FFFF:0:192.168.x.x, где x.x конкретный номер хоста. Хосты IPv6 адресуют хосты в IPv4 Internet с помощью IPv4-отображенных IPv6 адресов, т.е. адресов вида ::FFFF:x.x.x.x, где x.x.x.x IPv4 адрес. Хосты в IPv4 Internet адресуют IPv6 хосты в данной IPv6 подсети с помощью IPv4 адресов 192.168.x.x. Для того, чтобы включить механизм трансляции, необходимо включить в системе пересылку пакетов между интерфейсами системы (forwarding), т.е сделать систему маршрутизатором. Теперь, после того как трансляция включена, для того чтобы она заработала, необходимо просто подать на систему трафик, подлежащий трансляции. Для этого необходимо установить
138
машрутизацию IPv6 пакетов, идущих по адресам, начинающимся с префикса ::FFFF:0:0/96 на интерфейс siit (см. рис.10). Кроме того, необходимо установить в системе машрутизацию IPv4 пакетов из диапазона, предназначенного для IPv6 хостов, на интерфейс siit. Тогда приходящие в систему IPv6 пакеты с IPv4отображенным адресом назначения будут проходить через IPv6 стек и попадать из него на интерфейс siit, на котором они будут претерпевать трансляцию в формат IPv4. После трансляции пакеты будут попадать из интерфейса siit в стек протокола IPv4, и, поскольку включена маршрутизация, пересылаться этим стеком на реальный исходящий интерфейс и уходить в сеть. Аналогичные события будут происходить и с IPv4 пакетами, приходящими на один из IPv4 адресов, выделенных для IPv6 хостов. Реализация транслятора в виде драйвера (псевдо)сетевого интерфейса позволяет существенно упростить сам транслятор. Так, например, IP/ICMP транслятор, так же как и обычный маршрутизатор, должен отслеживать значение полей TTL и Hop Limit протоколов IPv4 и IPv6, соответственно. Входящие пакеты, у которых эти поля нулевые, транслятор должен сбрасывать и отсылать отправителю ICMP сообщение Time Exceeded. При реализации транслятора в виде драйвера сетевого интерфейса задача проверки этих полей ложится на сам стек IPv4 или IPv6. Точно так же, все необходимые проверки, которые должен выполнять маршрутизатор, а именно: проверка контрольных сумм заголовка IPv4, проверка соответствия размера пакета информации о размере, содержащейся в заголовке IP, проверка превышения длины пакета размера MTU на исходящем сетевом интерфейсе и т.д. - осуществляются самими стеками IPv4 и IPv6, а не транслятором.
6. Заключение В результате данной работы был реализован один из механизмов обеспечения совместимости протоколов IPv6 и IPv4 – бесконтекстный IP/ICMP транслятор, способный, вместе с другими механизмами, обеспечить плавный и безболезненный переход на протокол IPv6. В процессе работы были изучены особенности и тонкости реализации данного транслирующего механизма в среде операционной системы Linux.
Литература 1.
E. Nordmark, "Stateless IP/ICMP Translator (SIIT)", draft-ietf-ngtrans-siit04.txt, December 1998. 2. S. Deering, R. Hinden, Editors, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, December 1998. 3. S. Deering, R. Hinden, Editors, "IP Version 6 Addressing Architecture", RFC 2373, July 1998. 4. R. Gilligan, E. Nordmark, "Transition Mechanisms for IPv6 Hosts and Routers", RFC 1933, April 1996. 5. S. Deering, A. Conta, "Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6)", RFC 2463, December 1998. 6. J. Postel, "Internet Protocol", RFC 791, September 1981. 7. J. Postel, "Internet Control Message Protocol", RFC 792, September 1981. 8. J. Mogul, S. Deering, "Path MTU Discovery", RFC 1191, November 1990. 9. J. McCann, S. Deering, J. Mogul, "Path MTU Discovery for IP version 6", RFC 1981, August 1996. 10. K. Nichols, S. Blake, F. Baker, and D. L. Black, "Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers", RFC 2474, December 1998. 11. M. Fiuczynski, V. Lam, B. Bershad, “The Design and Implementation of an IPv6/IPv4 Network Address and Protocol Translator”, technical report of Department of Computer Science and Engineering, University of Washington 12. P. Srisuresh, K. Egevang, “The IP Network Address Translator (NAT)”, RFC 1631, May 1994
Рис. 10. Путь прохождения пакетов, подлежащих трансляции 139
140
Возможности использования технологии детерминированного хаоса в системах автономного адаптивного управления1 А. А. Жданов, А.Е. Устюжанин
Введение Одной из принципиальных черт человеческой памяти является способность человека запоминать как единый объект образ, состоящий из множества упорядоченных деталей, особенно часто упорядоченных во времени (везде ниже будем иметь в виду упорядоченность именно во времени). Для того, чтобы распознать такой образ, вспомнить и воспроизвести его в памяти, человеку бывает достаточно увидеть лишь небольшой фрагмент, относящийся к произвольной части такого образа, остальные упорядоченные фрагменты образа вспоминаются уже по ассоциации. Примерами могут служить запоминание мелодии, стихотворения, длинной дороги. По-видимому, такими свойствами обладает память не только человека, но и память других естественных организмов. Употребленное здесь понятие ассоциативности заставляет сравнить такую память с так называемой ассоциативной памятью, используемой в технических системах обработки информации. Ассоциативным подходом к использованию памяти в технических системах обработки информации называется подход, когда поиск информации происходит по части ее содержания. Ассоциативный подход используется, например, в ЭВМ для реализации сверхоперативной памяти и при работе с базами данных. Ассоциативными свойствами обладают также некоторые нейронные сети, например, нейронные сети Хопфилда и Хэмминга [1, 2]. При реализации ассоциативной памяти в нейронных сетях стремятся сделать так, чтобы при возбуждении некоторых нейронов возбуждался тот ансамбль нейронов, который включает первоначально возбужденные нейроны, а также и другие нейронные ансамбли, ассоциированные с первым, при этом предусматриваются средства для торможения процесса ассоциативного возбуждения в случае его лавинообразного расширения. В последнее время появился также новый подход, основанный на применении теории детерминированного хаоса [3-20], который подробнее будет рассмотрен ниже. 1
Однако использованное в указанных системах понимание ассоциативной памяти не вполне совпадает с тем феноменом естественной памяти, о котором мы говорим, поскольку в ассоциативной памяти упорядоченность запоминаемой информации во времени не является определяющим требованием. Соответственно, способ обращения к ассоциативной памяти не связан обязательно с упорядоченностью содержания данных. Например, в указанных реализациях ассоциативной памяти на нейронных сетях нейронные ансамбли возбуждаются в порядке, зависящем от ряда случайных причин. Напротив, в естественной памяти, как можно судить по собственным ощущениям, информация запоминается с сохранением порядка ее поступления (слова стихотворения, звуки мелодии), объединяясь при этом некоторым смысловым содержанием (технология некоторой операции, речь некоторого человека) и некоторым идентифицирующим признаком (название стихотворения, мелодии); наиболее хорошо запоминаются повторяющиеся последовательности данных (знакомая дорога), при этом в них запоминаются именно общие места; информация вспоминается в той последовательности, в которой она запоминалась (Вам с большим трудом удастся воспроизвести слова знакомого стихотворения в обратном порядке). Однако наиболее важное отличие мы усматриваем в следующем. Память современного компьютера оптимизируется по различным критериям, отражающим возможные требования пользователей и исполнителя пользовательских и системных программ. Напротив, память всякого живого организма оптимизирована с точки зрения вполне определенных целевых функций, единых для всех нервных систем. Этими целевыми функциями, по нашему убеждению, являются выживание и накопление знаний. Для того чтобы выжить, улучшить свое текущее состояние, нервная система имеет только одно средство – она должна воздействовать на окружающую ее среду, рассчитывая на определенные прогнозируемые нервной системой обратные реакции среды. Такой прогноз основывается на тех эмпирических и выводных знаниях, которые добыты данной нервной системой и хранятся в ее памяти. Таким образом, знания нервной системы должны отражать функциональные свойства среды, окружающей ее, т.е. приносить информацию об этих свойствах. Уточним, что нервную систему окружает тело организма и среда, в которую погружен организм, их совокупность и будем называть ниже просто средой. Информация о функциональных свойствах любого объекта, в данном случае среды, должна иметь вполне определенную структуру, именно, указывать, каким воздействием можно перевести данный объект из одного возможного его состояния в другое возможное его состояние. Другими словами, элементарное знание должно иметь вид последовательности импликаций, «начальное состояние объекта в момент t1» → «воздействие на объект в момент t2» → «возможные результирующие состояния объекта в момент t3».
Работа выполнена при поддержке РФФИ, грант № 0001-00372 141
142
Такая импликация отражает причинно-следственную связь явлений в нашей среде обитания, и самым тесным образом связана со временем, так как причина предшествует следствию именно во времени. Поэтому работа с данными, упорядоченными во времени, крайне важна для живых организмов. Анализ событий, последовательно происходящих во времени, является основой выявления причинно-следственных связей явлений в нашей среде обитания. Чтобы обеспечить выживание организмов в этом мире, их нервные системы должны иметь возможность запоминать временные последовательности данных о наблюдаемых явлениях и своих воздействиях, анализировать их, выявляя в них регулярности, и использовать выявленные регулярности для принятия решений на основании прогноза следствий альтернативных вариантов своих возможных действий. Из сказанного следует, что известные способы реализации ассоциативной памяти не вполне подходят для моделирования указанных свойств естественной памяти при моделировании систем управления, имитирующих нервные системы. Особенно это касается таких автоматических адаптивных систем управления, которые имитируют не отдельные свойства нервных систем, но их свойства в целом. Это управляющие системы, которые должны автоматически приспосабливаться к жизни в среде с заранее плохо известными им свойствами, это системы, в которых предусмотрены указанные целевые функции выживания и накопления знаний. Именно такого рода системы управления мы и будем рассматривать ниже. Мы полагаем, что для воспроизведения памяти с описанными выше свойствами, в автоматических адаптивных системах управления должны автоматически решаться следующие задачи. а) Задача автоматической классификации (формирования образов) пространственно-временных объектов, т.е. автоматическое обнаружение в пространстве признаков таких упорядоченных множеств пространственновременных объектов, которые можно ассоциировать в классы - образы в соответствии с некоторыми заданными правилами; б) Задача сохранения данных о сформированных классах - образах в некоторой “памяти образов”; в) Задача автоматического ассоциативного распознавания таких образов, т.е. выделение в памяти всех упорядоченных объектов, составляющих данный образ, при наблюдении только части принадлежащих ему объектов. Настоящая работа представляет предварительные результаты исследования возможностей построения памяти с указанного рода ассоциативными свойствами на основе технологии детерминированного хаоса. При исследованиях человеческого мозга была выдвинута гипотеза, что принципы работы человеческого мозга схожи с принципами работы технических систем, основанных на идеях детерминированного хаоса. Такие системы в 143
некоторых случаях заметно повышают эффективность обработки информации, и, одновременно, удобны для программной реализации. Тем самым, идеи детерминированного хаоса имеют, с одной стороны, глубокое бионическое обоснование, с другой стороны – могут дать важные практически полезные результаты. Оба этих свойства детерминированного хаоса являются привлекательными для систем автономного адаптивного управления (ААУ), разрабатываемых авторами настоящей работы [22-37]. Идея систем ААУ также имеет бионическое основание, поскольку в системах ААУ мы моделируем нервные системы. В управляющей системе ААУ отдельными ее подсистемами взаимосогласованно решаются задачи автоматической классификации, распознавания образов, представления знаний, принятия решений и некоторые другие. Основным полезным свойством систем ААУ является их способность осуществлять адаптивное управление объектами, для которых трудно составить точную математическую модель, на основании которой можно было бы применить какой-либо из традиционных методов управления. Проблема работы с образами протяженных упорядоченных во времени пространственно-временных объектов и организации ассоциативной памяти является актуальной для теории систем ААУ. Практически реализованные до настоящего момента системы ААУ позволяли решать задачу формирования и распознавания образов (ФРО) на данных по предыстории процесса управления длиной всего несколько тактов дискретного времени с прогнозированием всего на один-два такта вперед. При помощи технологий детерминированного хаоса удалось найти эффективный подход к расширению анализируемых и прогнозируемых временных диапазонов процесса управления. Были рассмотрены различные варианты построения памяти управляющей системы на основе детерминированного хаоса. Для исследования разработанной системы и проведения компьютерных экспериментов был построен программный комплекс, позволяющий собирать систему ААУ из модулей, реализующих ее функциональные подсистемы на базе различных подходов. В результате проведенного математического моделирования была показана принципиальная возможность использования технологии детерминированного хаоса для организации таких подсистем системы ААУ, как аппарат формирования и распознавания образов, база знаний и аппарат принятия решений. Данная технология позволяет управляющей системе работать с образами очень протяженных пространственно-временных явлений. Свойства системы были продемонстрированы на модельном примере, представляющем собой управляющую систему транспортного робота, движущегося по лабиринту, имеющему набор повторяющихся фрагментов. Настоящая работа представляет первые результаты исследования возможности применения технологии детерминированного хаоса для построения некоторых подсистем системы ААУ. 144
1. Имитационный управления
метод
автономного
адаптивного
Коротко представим основные положения разрабатываемой в ИСП РАН концепции адаптивных систем управления, называемых нами системами “автономного адаптивного управления” (ААУ) [22-37]. Системы ААУ моделируют некоторые черты естественных нервных систем, поэтому проводятся аналогии между определенными подсистемами системы ААУ и биологическими объектами. Так под объектом управления (ОУ) понимается модель организма, под управляющей системой (УС) – модель нервной системы, под системой – совокупность УС, ОУ и среды. При построении УС принимаются следующие четыре исходные условия, характерные для нервных систем. Условие автономности, под которым понимается то обстоятельство, что УС является подсистемой ОУ, т.е. УС находится на борту ОУ и осуществляет управление на основе знаний, добываемых самостоятельно, взаимодействуя со своим окружением посредством блока датчиков (БД) и исполнительного органа (ИО), входящих в состав ОУ и не входящих в УС. Условие дискретности, которое отражает дискретность структуры УС и принципа ее функционирования. Так, дискретными являются конечные множества нейронов, связей, датчиков, исполнителей, нервных импульсов, образов, моментов времени. Однако при этом возможен непрерывный характер изменения некоторых параметров УС, таких как размеры отдельных синапсов, частотные характеристики импульсных последовательностей, и некоторых других параметров. Однако элементарной дискретной единицей информации в УС полагается образ. Условие максимальной начальной приспособленности отражает наличие приспособленности ОУ и УС к усредненным условиям жизни ОУ в данной среде в результате действия механизмов типа естественного эволюционного отбора. Такие механизмы отбора определяют типы датчиков и исполнителей, классы потенциально возможных в данной системе образов, оценки качества важнейших для ОУ образов, и т.п. При синтезе ОУ и УС процесс естественного отбора может быть заменен, например, оптимизацией системы на основе использования априорной информации. Условие минимума исходных знаний отражает наличие информационных пространств, которые должны быть заполнены знаниями, найденными УС в процессе функционирования в реальной системе. Это условие соответствует наличию неопределенности свойств системы, максимальной для УС в момент начала ее функционирования. Адаптивностью УС мы называем способность УС накапливать знания, которые используются ею для управления. При этом качество управления возрастает, поскольку накопление знаний снижает 145
неопределенность свойств модели окружающей среды, которую в совокупности представляют собой накопленные знания. Принимаются следующие целевые функции УС: а) выживание ОУ и б) накопление знаний. Эти две целевые функции взаимосвязаны в том отношении, что достижение одной из них повышает вероятность достижения другой. Из сказанного вынужденно следует представление о системе (рис. 1), в котором можно видеть ОУ, погруженным в среду, и УС, погруженной в ОУ. Пусть каждый из этих макрообъектов оказывает воздействия на систему через свой выход и воспринимает воздействия системы через свой вход.
Рис. 1. Кроме того, в системе важно наличие источников случайных воздействий (белые кружки на рисунке - истоки) и мест поглощения воздействий (черные кружки на рисунке - стоки). Такая схема позволяет увидеть все возможные маршруты распространения воздействий в системе (помеченные буквами стрелки на рисунке) [22, 36]. Очевидно, что для достижения своих целевых функций, УС должна найти те из воздействий h, которые образуют цикл управляемого взаимодействия (УВ) h d i a h … , зафиксировать информационное отображение цикла УВ в своей памяти – базе знаний (БЗ), оценить полезность тех или иных элементов знаний и использовать эти знания для выживания, одновременно стремясь к получению и накоплению новых знаний. Здесь a это информационный процесс в УС, h – процесс преобразования информационных команд в физические воздействия, d это различные процессы в окружающей среде, i – процесс преобразования части входных воздействий в информационные входные сигналы для УС. Наличие в системе истоков и стоков вносит в УВ многочисленные случайные компоненты и приводит к потерям информации. 146
Накапливая знания, УС уменьшает неопределенность своей БЗ, отображающей УВ. Подобное макроописание позволяет понять задачу, которую должна решать УС. В общем виде можно видеть следующую ее постановку. На заданное множество входных полюсов УС v1, v2, …, vi, …, vn (например, это n бинарных выходов БД) поступает входной поток информации. Пусть, например, это будет эквидистантная во времени последовательность двоичных векторов Va(t1), Vb(t2),…, Vc(tk),…, Vd(t), где t – текущий момент времени. Если последовательность не эквидистантная, то должны быть средства синхронизации потоков данных. Согласно рис. 1, семантически каждый вектор Vc(tk) может содержать информацию, пришедшую ко входу УС по маршрутам i, b и/или p. Здесь i это информация, поступившая с датчиков, b – информация, отражающая действия, совершенные УС, p это помехи от истоков в ОУ (информация от i и b также содержит случайные компоненты). Информация, поступающая по маршрутам i, b и p, может отображаться на определенные подмножества компонент вектора Vc(tk). Первая задача, которую должна и может решать УС, состоит в нахождении неслучайных регулярных пространственно-временных комбинаций компонент в потоке входных векторов Va(t1), Vb(t2),…, Vc(tk),…, Vd(t). Произвольные примеры трех таких образов показаны на рис. 2. Если УС обнаруживает наличие такой регулярности, то УС должна: a) запомнить информацию о ней как самостоятельный объект – образ; b) уметь распознавать прообраз этого образа во входной информации при его последующих появлениях, где под прообразом будем понимать регулярность, которая привела к формированию образа; c) при накоплении достаточной статистической надежности – уметь распознавать образ протяженного во времени прообраза раньше, чем закончится его наблюдение на входных полюсах и при наличии помех; d) оценить соответствие этого образа целевой функции выживания ОУ.
Пути к решению последней задачи мы видим в организации в УС специальной подсистемы, которая эквивалентна аппарату эмоций в живом организме. Это многофункциональная подсистема [25], основная функция которой – соотносить отвлеченные информационные сигналы, например, сигналы о распознавании образов, отображающих текущие состояния ОУ, с объективной полезностью или опасностью их прообразов для выживания ОУ. В результате сформированные образы наделяются своими качественными оценками. Оценки базовых образов (изначально заложенные в УС образы наиболее важных для выживания состояний) могут быть найдены на основе анализа эмпирических данных и априорной информации. Оценки для образов, формируемых в процессе функционирования ОУ, могут быть найдены УС опытным путем посредством корреляционного анализа фактов распознавания этих образов и значений текущей интегральной оценки состояния ОУ, которую обозначим St. В свою очередь, текущее значение оценки St зависит от оценок всех распознанных в текущий момент образов. Здесь обратим внимание на то, что целевая функция выживания реализуется через цель максимизации оценок St. Это обеспечивает внутреннюю активность УС, тем самым, работая и на вторую целевую функцию – накопление знаний. В процессе управления текущее значение оценки St определяет также целесообразную глубину просмотра базы знаний при принятии решений в текущей ситуации. Пусть УС сформировала некоторый образ, запомнила его в памяти сформированных образов в виде объекта, который обозначим Ok, и в некоторый момент t распознает его, что обозначим как Otk =1 (если сформированный образ Ok не распознан в момент t, то полагаем Otk =0). Пусть, например, прообразом данного образа является некоторый пространственно-временной процесс длительностью T тактов, но УС распознала образ уже через T’ тактов после его начала tks, и T’< T. Если семантически прообраз данного образа в векторах Va(tks), Vb(tks+1),…, Vc(tks+T’),…, Vd(tks+T) представлял собой отображение информации, пришедшей на вход УС по маршруту i (см. рис. 1), то это сравнительно простой случай, интересный, в основном, тем, что УС имеет прогноз, в частности, изменения оценки своего состояния St к моменту, когда завершится наблюдение всего прообраза. Одновременно может быть распознано некоторое множество образов. Однако ситуация становится более интересной, если в прообразе распознанного образа Ok имел место хотя бы один вектор V(t), отражающий информацию, пришедшую к УС по маршруту b, т.е. в прообраз входило некоторое действие, совершенное УС (например, в нервной системе это сигнал от рецепторов о том, что была сокращена такая-то мышца в результате соответствующей команды). Обозначим такое действие символом Yl. Тем самым прообраз образа Ok (рис. 3a) можно разбить на три последовательных во времени составляющих: 1) информация о ситуации Xa, 2) информация о действии Yl, 3) информация о ситуации Xb. Поскольку, по определению, прообраз сформированного образа – явление не случайное, то данную тройку (Xa, Yl, Xb)
Рис. 2. 147
148
можно интерпретировать как импликацию условие действие следствие. Очевидно, что в данной ситуации могло быть распознано два или более образов Ok (рис. 3b), имеющих одинаковое условие (ситуацию Xa), разные возможные альтернативные действия (действие Yl) и, возможно, разные следствия (ситуацию Xb). Итак, если в некоторый момент а) УС одновременно распознает несколько временных образов, при этом б) распознавание наступило раньше окончания наблюдения составляющей Xa прообраза, в) в составе прообразов ожидаются альтернативные действия Y1, Y2,…, ведущие к альтернативным следствиям Xb, Xc,…, г) распознанные образы имеют свои оценки, то появляется возможность принятия решения, на основании сравнения ожидаемых приращений интегральной оценки качества состояния St для альтернативных действий [23, 25].
Прообраз образа Ok
a)
Условие Xa
t1
Действие Ya
t2
Xb
t3
Время
b)
Xa Xa Xa
Y1
Xb
Y2
Xc
Y3
Xd
Рис. 3. 149
Если при распознавании образа Ok вида условие действие следствие, его «следствие» соответствует «условиям» других образов такого же вида условие действие следствие, записанным в БЗ, то прогнозируемая причинноследственная цепочка образов и действий продолжается на несколько шагов в будущее, позволяя УС глубоко планировать свои действия. Для этого, конечно, УС должна обладать специальными языковыми средствами манипулирования с такими образами и действиями, а у нас появляются основания говорить об интеллекте этой УС [27]. Поскольку постоянно идет формирование новых образов, то возможна ситуация, когда альтернативные действия, приносящие ранее одинаковый ожидаемый конечный результат - распознавание одинаковых образов, начнут различаться в отношении новых сформированных образов, т.е. – более тонких последствий выбираемого действия. Учет этих различий делает действия УС со временем все более точными, а их следствия – все более точно предсказуемыми. Это одна из возможностей саморазвития УС. Рассмотренная интеллектуальная управляющая система обладает следующими основными свойствами. 1. УС обладает внутренней активностью, направленной на цели выживания, улучшения текущего состояния и накопления знаний. 2. Накопление знаний в УС повышает вероятность ее выживания. 3. УС обладает свойствами адаптивности и саморазвития. Именно, формируются и оцениваются новые образы, формируются и уточняются новые действия, увеличивается глубина прогнозирования следствий альтернативных вариантов действий и др. 4. Знания УС сильно зависят от ее индивидуального опыта, в том числе от случайных событий, т.е. УС обладает своей индивидуальностью. Система с подобными свойствами не соответствует общепринятому пониманию и назначению систем искусственного интеллекта (ИИ), к которым сегодня относят экспертные системы, распознающие системы, нейросети, лингвистические процессоры и робототехнику. Поэтому предлагается выделить системы с подобными свойствами в отдельное направление системы автономного искусственного интеллекта (АИИ) [27]. Если основное назначение систем ИИ - быть исполнителями заданий, поступивших извне от пользователя, то назначение систем АИИ – выжить и накопить знания, подчиняясь относительно независимому от внешних управляющих воздействий внутреннему целеполаганию. Помимо теоретического интереса, прагматическое значение систем АИИ, имитирующих естественные организмы, может состоять в их способности к выживанию, работе и накоплению знаний в плохоформализуемых условиях, требующих адаптации и саморазвития. Как видно из сделанного качественного описания рассматриваемых систем, их реализация сопряжена с необходимостью решения следующих непростых задач: 150
1) задачи формирования и распознавания образов (ФРО) в потоке входной многоканальной информации, 2) задачи построения базы знаний и аппарата принятия решений, 3) задачи построения аппарата эмоций.
1.1. Задача формирования и распознавания образов Задача ФРО описана в работах [24-26,32]. В общем виде она имеет следующую постановку. На многоканальный вход УС поступает двоичная информация о непрерывных воздействиях различной физической природы, испытываемых ОУ. Аппарат ФРО должен в процессе самообучения сформировать множество дискретных образов, соответствующих классам пространственно-временных регулярностей входной информации и далее распознавать такие образы. Распознаваемые образы должны порождать формирование образов над образами, т.е. образов более высокого порядка. Переход от континуальных величин к дискретным должен происходить уже в БД. В нетривиальных случаях при отсутствии априорного алфавита классов такого рода задача является трудной. В некоторых условиях для построения БД и/или начальных трактов аппарата ФРО возможно применение персептронов и генетического подхода, либо использование аппарата эмоций в качестве учителя. Напомним, что задача распознавания образов даже таких простых регулярностей, как периодические компоненты во временных рядах, требует применения сложного математического аппарата анализа временных рядов. Мы полагаем, что поиск неслучайных составляющих во входном многоканальном потоке входных данных должен основываться на аппарате корреляционного анализа, тогда решение о формировании нового образа может приниматься при накоплении достаточных статистических оснований.
Заметим, что предложенная схема допускает весьма простые решения. Так, в указанной тройке множеств «множество образов условия – множество образов действия – множество образов результатов», каждое из распознаваемых множеств может быть представлено, например, всего одним образом. Даже такое простое решение позволяет строить практически полезные приложения [30,3638]. Однако в общем случае каждый из образов указанной тройки может кодировать очень длинную упорядоченную во времени цепочку подобразов. Реализация такой возможности существенно расширила бы возможности практического использования метода, чему и посвящена настоящая работа.
1.2. Построение базы знаний и аппарата принятия решений Задача построения базы знаний сводится к накоплению информации о среде, позволяющей выбирать действия, опираясь на некоторую предысторию, на текущее состояние управляемой системы и на прогноз следствий альтернативных действий. Наиболее органичным подходом является сохранение в БЗ троек вида образ условия – образ действия – образ следствия. В элементарном случае БЗ может быть представлена трехмерной матрицей, измерения и размерности которой соответствуют образам указанной тройки множеств. Принятие решения осуществляется выбором элемента-действия из данной матрицы, которому соответствует наилучший образ-следствие.
1.3. Построение аппарата эмоций Идея определения оценок качества образов основана на корреляционном анализе сигналов от распознанных образов и сигналов оценки текущего состояния ОУ. Этот подход подробно описан в работе [25]. В целом, управляющую систему, построенную по методу ААУ, можно изобразить следующей схемой (рис. 4). 151
Рис. 4.
2. Детерминированный хаос. Представление о процессах обработки информации на основе сложной динамики Технология использования детерминированного хаоса для организации хранилищ информации, способных запоминать длинные последовательности символов, взята нами из работ А.С. Дмитриева [3, 33-36]. В настоящей главе мы приводим краткое изложение этой технологии по указанным публикациям. 152
Исследования человеческого мозга за последнее время показали, что обработка информации животными и людьми протекает по совершенно иным алгоритмам, чем алгоритмы, используемые сейчас в электронной технике. Например, на основе анализа электроэнцефалограмм было показано существование детерминированных хаотических режимов в мозге для ряда состояний активности человека [4-10]. Электроэнцефалограмма в том или ином виде отражает информационные процессы в мозге. Поэтому указанные результаты позволяют предположить, что мозг, в отличие от компьютеров, работает также с хаотическими в некотором смысле сигналами и ведет обработку информации, используя сложную динамику такой нелинейной системы, как нейронная. Если сложная динамическая система, поведение которой в общем случае считается хаотическим или случайным, при некоторых условиях меняет свои состояния по некоторым детерминированным законам, то говорят, что данная система может находиться в режимах с детерминированным хаосом, или что она обладает таковыми.
2.1. Информация и динамические системы Исследования систем с детерминированным хаосом также свидетельствуют о тесной связи между теорией динамических систем и информационными процессами. Ряд основополагающих результатов динамической теории формулируется применительно к объектам, так или иначе связанным с информацией [10-12]. В [13] анализируется вопрос об информационных потоках в одномерных отображениях. Автор ссылается на исследования [14], в которых аргументируется тот факт, что информация является фундаментальной концепцией в теории динамических систем и хаоса. В частности, чувствительность к начальным условиям строго относится к созданию информации. Далее автор рассматривает динамическую систему, описываемую отображением f интервала в себя, и исследует, как итерация f индуцирует специальный процесс, который автор и называет информационным потоком. Еще одна причина, связанная с необходимостью понимания динамического хаоса с информационной точки зрения — наличие естественных объектов с детерминированной хаотической динамикой [15] или со смешанной динамикой, содержащей в себе как детерминированный хаос, так и случайный процесс.
2.2. Аттракторы и бифуркационные явления в одномерных отображениях Имеется множество динамических систем, которые могут производить хаос. Однако мы будем говорить только о преобразованиях одного типа — одномерных отображениях, которые могут быть записаны в виде
Xn+1 = f ( Xn, a ), 153
где а — вектор параметров. Данное отображение может обладать чрезвычайно широким набором явлений сложной динамики, присущим хаотическим системам общего вида, и, как станет ясно из дальнейшего, может служить полноценной основой для моделирования различных операций обработки информации с использованием хаоса. В отображениях с хаосом вследствие неустойчивости возникает неопределенность в положении фазовой траектории. Степень этой неопределенности ограничивается динамическими уравнениями, связывающими предыдущее и последующее состояния системы. Информация о начальном состоянии системы (заданная всегда с конечной точностью) теряется при переходе от предыдущего состояния к последующему. Поэтому можно говорить о производстве информации в таких системах. Если же отображение демонстрирует регулярное поведение (например, периодические колебания), то его будущее полностью определено и производство информации равно нулю. Стартуя из любых начальных условий, образующих бассейн притяжения регулярного аттрактора, траектория отображения притягивается к этому аттрактору (неподвижной точке, предельному циклу), и информация о начальных условиях теряется, поскольку траектории, выходящие из разных начальных точек, становятся через некоторое время неразличимыми. Информация "исчезает", и поэтому регулярные аттракторы можно рассматривать как "стоки" информации. Таким образом, нелинейные одномерные отображения способны как производить, так и "уничтожать" информацию. Каждую траекторию динамической системы можно рассматривать как некоторый информационный сигнал. Тем самым, совокупность траекторий отображения представляет собой своеобразное "хранилище" информации в виде множества траекторий системы. Это "хранилище" обладает рядом полезных свойств, проявление которых зависит от того, имеются ли аттракторы в динамической системе и какого они типа. Рассмотрим некоторые из этих свойств. Если в момент времени t = t0 задать начальные условия, то формально траектория отображения известна и однозначно определена для всех t > t0 (аналог теоремы Коши для отображений). Если траектории вдоль ее длины сопоставлен информационный сигнал, он может быть воспроизведен путем итерирования отображения с заданными начальными условиями, т.е. информация извлекается из памяти путем решения эволюционного уравнения. "Хранилище" информации как динамическая память обладает естественными ассоциативными свойствами. Действительно, задавая любой фрагмент сигнала, можно воспроизвести все его последующие значения, а в случае циклического сигнала — и весь сигнал целиком. Если в отображении имеется аттрактор — устойчивый предельный цикл, то все траектории со временем стягиваются к нему. Периодическую траекторию, 154
соответствующую предельному циклу, можно рассматривать как периодически воспроизводимый информационный сигнал. Объем информации в таком сигнале определяется длиной цикла и степенью его изрезанности (информационной насыщенностью). За последние несколько лет были разработаны методы синтеза специальных отображений с записанной информацией, соответствующие алгоритмы и программные комплексы, практически не имеющие ограничений на объем информации, записываемой на предельных циклах отображений. Кроме того, итерации отображения вдоль цикла нейтральны в смысле сжатия информации: они не приводят ни к исчезновению старой информации, ни к порождению новой и просто воспроизводят периодически одну и ту же информацию. т.е. идеально сохраняют ее. По перечисленным причинам будем рассматривать предельные циклы отображений в качестве основных объектов для записи и хранения информации в отображениях с хаосом. Рассмотрим случай, когда отображение имеет два или более регулярных аттрактора. В зависимости от начальных условий траектория притягивается к тому или иному аттрактору. Отображение тем самым "различает" начальные условия и "классифицирует" их на несколько типов по числу аттракторов. Оно сжимает множество всех начальных условий в несколько классов, т.е. способно выполнять роль распознавателя (классификатора). В таком отображении информация как бы обобщается, "производства" информации нет. Результат функционирования система переносит на новый уровень иерархии: вместо исходного множества траекторий имеется несколько специальных траекторий — аттракторов, каждый из которых характеризует класс информационных объектов. В качестве среды для записи и хранения информации в [16] было предложено использовать динамическую систему с дискретным временем — одномерное отображение отрезка в себя. В этой простой системе была продемонстрирована возможность записи на предельных циклах, показана возможность реализации ассоциативной памяти, распознавания образов и ряда других базовых функций обработки информации с использованием сложной динамики [16-18]. Рассмотрим процедуру записи и восстановления информации на основе предельных циклов одномерных динамических систем. Записываемая информация представляется в виде информационных блоков — конечных последовательностей вида
a1, a2, a3, …, an Каждый элемент аi информационного блока принадлежит конечному упорядоченному множеству А = {aj, j = 1 ... N}, которое далее будем называть алфавитом. Примерами таких алфавитов являются кириллица, нотная азбука, набор ASCII-кодов и т.д. 155
Следует заметить, что при записи на замкнутую траекторию информационный блок мысленно "сшивается" в кольцо, так что после последнего элемента an следует первый а1, поэтому фрагментом информационного блока будем называть односвязный "отрезок" этого кольца. К синтезируемой функции f(x) одномерного отображения xn+1 = f (xn) с записанной информацией предъявляются следующие требования: предельный цикл, несущий информацию об информационном блоке длиной n, последовательно проходит через n точек; между точками цикла и элементами соответствующего информационного блока существует взаимно однозначное соответствие; контролируется характер устойчивости предельного цикла. Синтез одномерного отображения начинается с того, что в одномерном фазовом пространстве — отрезке [0, 1], для каждого из записываемых информационных блоков а1, a2 ... an, строится замкнутая траектория - цикл = {x1 … xm}, каждая точка которого взаимно однозначно связана с соответствующим фрагментом информационного блока. После того, как в фазовом пространстве построен скелет замкнутых траекторий-циклов, отвечающих записанным информационным блокам, конструируется собственно функция f(x). Для этого на плоскости (Xm, Xm+1) откладываются пары последовательных точек всех циклов (хi , xi+1). Любая однозначная кривая, проходящая через эти точки, определяет функцию f(x) одномерной динамической системы, удовлетворяющую первым двум требованиям, предъявляемым к функции отображения. Для управления устойчивостью циклов через точки на плоскости (Хт, Хт+1) проводятся короткие отрезки с фиксированным наклоном s (далее называемые информативными участками). Как известно, устойчивость предельного цикла определяется его мультипликатором . В случае одномерного отображения для цикла n = {x1, …, xn} он равен = f`(x1)… f`(xn), а в данном случае = sn. При < 1 (s < 1) цикл устойчив, при > 1 (s > 1) — неустойчив. Синтез функции f(x) искомого одномерного отображения завершается последовательным соединением концов информативных участков между собой и концами отрезка [0,1] прямыми линиями. Пример 1. Продемонстрируем принцип записи информации на предельных циклах одномерных динамических систем на примере записи информационного блока — слова "бег". В качестве алфавита возьмем подмножество кириллицы: A = {а, б, в, г, д, е, ж, з, и, к}, длина алфавита N = 10. Разделим фазовое пространство — единичный отрезок I = [0, 1] — на N регионов — отрезков длиной 0,1 и каждому из них поставим в соответствие букву — элемент алфавита (рис. 5). Попадание фазовой траектории на тот или иной отрезок (тот или иной регион фазового пространства) будем интерпретировать как появление на "выходе" динамической системы соответствующею элемента алфавита. 156
случае описанную выше процедуру придется немного усложнить, введя понятие уровня записи, иначе отображение получится неоднозначным. Проведем запись этих слов на втором уровне.
1 0.9
Как и в предыдущем случае, для каждого информационного блока строим свой цикл n = {x1, …, xn}, каждая точка х, которого будет определяться не одним элементом, информационного блока, а парой соседних элементов (фрагментом длины 2): хj = (mj - 1)/N + (mj+1 - 0,5)/N2. Чтобы вычислить эту точку, единичный отрезок I делим на N регионов первого уровня и ставим им в соответствие свои элементы алфавита. Каждый из этих регионов, в свою очередь, делим на N регионов второго уровня, и с каждым из них также сопоставляем свой элемент алфавита.
0.8 0.7
X(n+1)
0.6 0.5
Для информационного блока "бег" три точки цикла 31 связаны с фрагментами "бe", "ег", "гб". Чтобы найти точку цикла, соответствующую фрагменту "бе" в регионе первого уровня "б" возьмем регион второго уровня "е", центр этого региона поставим в соответствие фрагменту "бе". Аналогично поступим с другими фрагментами слов "бег" и "вид". В результате получим два цикла n1,2 однозначно связанные с этими информационными блоками.
0.4 0.3 0.2 0.1
Для построения функции f(x) отображения с этими циклами отложим на плоскости (Xn, Xn+1) точки с координатами (xj, xj+1), где xj, xj+1 — последовательные точки циклов 31 и 32. Для управления устойчивостью циклов через каждую такую точку проведем информационный отрезок с фиксированным наклоном s, как в примере 1, но на этот раз проведем его до границ участков уровня 2.
0 0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
X(n)
Рис. 5. Отображение с одним циклом, несущим слово "бег". Теперь для информационного блока "бег" построим цикл 3 = {x1, x2, x3} = {0,15; 0,55; 0,35}. Каждая точка этого цикла однозначно связана с одним из элементов (фрагментом единичной длины) информационного блока, и представляет собой центр соответствующего региона xj = (mj - 0,5)/N, где mj — порядковый номер элемента блока аi в алфавите. После того как в одномерном фазовом пространстве построен цикл, отвечающий записанному информационному блоку, на плоскости (Xm, Xm+1) отложим точки вида (xi, xi+1): (0,15; 0,55), (0,55; 0,35), (0,35; 0,15). Через каждую из них проведем отрезок с наклоном s = 0,5, доходящий до границ региона. Эти информативные отрезки обеспечивают устойчивость цикла. Соединим концы информативных участков между собой и с концами отрезка [0, 1] прямыми линиями. Синтез функции f(x) одномерного отображения xn+1 = f(xn) закончен.
Синтез функции f(x) завершается последовательным соединением концов информативных отрезков между собой и с концами единичного отрезка прямыми линиями (рис. 6). Аналогично может быть произведена запись информации на произвольном уровне q. Каждая точка соответствующего цикла определяется фрагментом длиной q соответствующего информационного блока, а длина информативных интервалов (проекций информативных участков) составляет N-q, это длина региона уровня q. Выбор уровня записи диктуется, во-первых, требованием однозначности функции отображения f(x) (ограничение снизу), во-вторых, точностью вычислений (ограничение сверху), поскольку с ростом уровня записи уменьшается длина информативных интервалов.
2.3. Уровень записи Пример 2. Попробуем записать на одном отображении два слова "бег" и "вид" на двух предельных циклах. Будем использовать алфавит из примера 1. В этом 157
158
При задании произвольных начальных условий попадание фазовой траектории системы на тот или иной информационный предельный цикл для стороннего наблюдателя представляется случайным. Однако рассматриваемый принцип записи информации дает возможность извлечения конкретного информационного блока, если известна какая-либо его малая часть (цитата, фрагмент). Если известен точный фрагмент информационного блока длиной не меньшей, чем номер уровня записи, то, используя описанную выше процедуру построения точек цикла, по предъявленному фрагменту информационного блока можно восстановить, по крайней мере, одну точку соответствующего предельного цикла и, проитерировав отображение, восстановить весь информационный блок. Свойство ассоциативного доступа к записанной информации по известному фрагменту (ассоциативная память) напрямую вытекает из динамических свойств отображения и аттракторов - носителей информации.
1 0.9 0.8 0.7 X(n+1)
0.6 0.5 0.4 0.3 0.2
2.5. Кодирование информационных блоков
0.1 0 0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
X(n)
Рис. 6. Функция отображения: слова "бег" и "вид" записаны на двух циклах на втором уровне.
2.4. Ассоциативное извлечение информации Восстановление (извлечение) информации, записанной на предельных циклах одномерных отображений, наиболее просто осуществляется при записи информации на устойчивых циклах (при |s| < 1). При этом проекции информативных участков на ось Хт информативные интервалы) составляют области гарантированной (непосредственной) сходимости фазовой траектории к предельным циклам. При задании начальных условий x0 на одном из информативных интервалов фазовая траектория динамической системы быстро сходится к соответствующему предельному циклу, а на "выходе" отображения наблюдается воспроизведение записанного информационного блока, поскольку фазовая траектория системы при этом последовательно обходит соответствующие регионы первого уровня. При задании начальных условий x0 на неинформативном участке отображения выходу траектории на предельный цикл предшествует переходный хаос, когда фазовая траектория системы блуждает по неинформативным участкам отображения. Рано или поздно она попадает на информативный участок отображения и сходится к тому или иному предельному циклу с записанной информацией. 159
Анализ информационных последовательностей (изображений, текстов и т.д.) показывает, что наибольшие трудности с их записью связаны с длинными однородными участками, хотя здравый смысл подсказывает, что они содержат немного информации. Эти соображения приводят к мысли о записи предварительно сжатой информации, но сжатой особым образом, чтобы обеспечить запись на уровне q. Процесс сжатия информации (устранения избыточности) назовем "ортогонализацией", чтобы подчеркнуть, что ее целью является обеспечение записываемости образов [19]. Один из возможных алгоритмов заключается в кодировании информационных последовательностей с построением алфавита повторяющихся фрагментов. Идея такова: если в информационных блоках обнаруживается повторяющийся фрагмент длиной q, то алфавит расширяется на один символ, представляющий собой этот фрагмент, а в последовательностях он кодируется этим новым символом. Получаются новые информационные блоки меньшей длины, выраженные в алфавите длиной (N + 1). Процедура повторяется до тех пор, пока они не станут "ортогональными", т.е. не содержащими одинаковых фрагментов длиной q. В результате применения такого алгоритма получаются ортогональные, более короткие закодированные информационные последовательности и расширенный алфавит, состоящий из исходного алфавита длиной N и дополнительного, элементы которого состоят из некоторого фрагмента длиной q и символа, представляющего (кодирующего) этот фрагмент в последовательностях. Таким образом, ортогонализация состоит в устранении избыточной информации в виде повторяющихся фрагментов за счет кодирования их более короткими 160
символами. В отличие от рассмотренного выше подхода, где запись обеспечивалась увеличением ее уровня, в данном случае фиксируется уровень и наращивается алфавит. Это дает принципиальную возможность записи любой совокупности информационных блоков на любом уровне, начиная со второго. Данный метод кодирования информационных блоков является обратимым, потерь информации не происходит. Для декодирования информации символы дополнительного алфавита в закодированной последовательности заменяются фрагментами длиной q из алфавита. Эта процедура может повторяться несколько раз, либо следует предварительно выразить все фрагменты дополнительного алфавита через элементы начального алфавита. Естественно, процедура кодирования неоднозначна. Окончательный вид закодированных последовательностей, расширенного алфавита, их длина определяются порядком пополнения алфавита совпадающими фрагментами, т.е. процедурой их поиска.
2.6. Сжатие информации Как отмечалось выше, метод кодирования (ортогонализации) информационных последовательностей разработан для записи любого набора информационных блоков на одномерном отображении. "Побочным" результатом ортогонализации является обратимое (без потерь) сжатие информации — уменьшение общего объема данных, необходимых для полного и точного описания информационных объектов, например текстов или изображений. Если взглянуть на описанный метод ортогонализации как на метод сжатия информации, то оказывается, что коэффициент сжатия, достигаемый применением этого метода, примерно совпадают с тем, что дают другие известные методы сжатия информации без потерь — арифметический, ЛемпеляЗива, Хаффмана.
2.7. Ассоциативное извлечение информации при использовании кодирования Для реализации ассоциативной памяти, т.е. восстановления записанного образа по его произвольному фрагменту, необходимо задать начальные условия, лежащие на соответствующем аттракторе. Для этого нужно знать фрагмент (aj ai+1…aj+1+q-1) длиной q информационного блока и вычислить начальную точку x0 q
x0 k 1
aj k 1
(1)
Nk
При записи на уровне q сначала проводится ортогонализация информационных блоков, а затем закодированные блоки записываются на предельные циклы отображения. Если известен фрагмент закодированного информационного блока 161
длиной q, то по нему, согласно (1), может быть построена начальная точка х0, восстановлен закодированный информационный блок, декодирован исходный информационный блок. Однако гораздо больший интерес представляет восстановление последовательности не по фрагменту закодированного блока, а по фрагменту исходного паттерна в исходном алфавите. Для реализации ассоциативного доступа в рассматриваемом случае необходимо сначала получить из предъявленного фрагмента паттерна в исходном алфавите соответствующий фрагмент закодированной информационной последовательности. Для этого нужно сначала закодировать его, пользуясь имеющимся в наличии дополнительным алфавитом — таблицей фрагментов, полученным при ортогонализации информационных блоков. Проблема заключается в том, что фрагмент, предъявленный для распознавания, может начинаться с произвольного элемента исходного информационного блока, включая и такие, которые не существует в закодированном блоке, потому что вошли в состав фрагментов, замененных одним символом. Пусть, например, блок (abcdefghijk) после кодирования на третьем уровне принял вид (xdyhz), где х = (abc), у = (efg), z = (ijk), а системе ассоциативной памяти предъявлен фрагмент исходного блока (cdefghi). При преобразовании предъявляемого фрагмента из исходного в новый алфавит получается некая новая последовательность (cdyhi), содержащая "правильный" кусок закодированного блока (dyh) в середине и "неправильные" элементы по краям. Чтобы "отсеять" их, используем следующую процедуру. По первым q элементам закодированного последовательного фрагмента строим начальную точку, согласно (1). Затем, используя знание отображения, определяем, попадает ли она на информативный интервал. Если х0 не попадает на информативный интервал, значит, по крайней мере, первый элемент закодированного последовательного фрагмента "неправильный". В таком случае переходим к следующему элементу, и так до тех пор, пока не окажется, что x0 попадает на информативный интервал. Некоторый текущий фрагмент (b1b2…bq), из которого получена начальная точка x0, является кандидатом на начало "правильной" части закодированного фрагмента. Чтобы убедиться в этом, проитерируем отображение несколько раз. Начальная точка x0 порождает последовательность итераций х0, x1=f(x0), x2=f(f(x0)), …, а также соответствующий информационный поток c0 = int( Nx0 ), c1, c2, … . Если (b1b2…bq) действительно является "правильным" участком, и "неправильные" элементы спереди уже отфильтрованы, то c0=b1, c1=b2 и т.д. Если это не так, значит, попадание на информативный интервал было случайным, и элемент последовательности b1 тоже "неправильный". Если в закодированном последовательном фрагменте имеется "правильный" кусок, по крайней мере, длиной q, то он будет найден таким образом. Если длина его не меньше q, его можно использовать для получения начальных условий на
162
аттракторе. После того как получена начальная точка x0, легко восстановить всю информационную последовательность и, соответственно, весь паттерн. Если весь закодированный фрагмент просмотрен, а найти начальную точку на аттракторе не удалось, значит, длина фрагмента была недостаточна — после кодирования в нем не нашлось "правильного" фрагмента длиной q. Таким образом, система ассоциативной памяти, построенная на описанных принципах, в ответ на предъявленный информационный блок или его часть практически мгновенно формирует один из двух возможных откликов: либо возвращает начальное условие x0 на соответствующем аттракторе — предельном цикле, по которому может быть полностью восстановлен блок; либо дает ответ, что предъявленной информации недостаточно для однозначного формирования начального условия на аттракторе, это же происходит и тогда, когда предъявленный блок не записан на отображении. При предъявлении некоторого фрагмента блока система ассоциативной памяти либо безошибочно восстанавливает информационный блок, либо сообщает о неспособности сделать это. Ошибка невозможна в силу однозначности процедуры кодирования предъявляемого фрагмента, "ортогональности" записанных информационных блоков, однозначности самого отображения, а также благодаря использованию при формировании начального условия описанной выше процедуры сравнения закодированного фрагмента с порождаемым информационным потоком. Следует заметить, что формирование начального условия на аттракторе и соответственно восстановление исходного паттерна по его фрагменту происходит без сравнения предъявляемого фрагмента с каждым из записанных образов. После кодирования предъявляемого фрагмента для вычисления начальной точки x0 может понадобиться выполнение лишь нескольких итераций для проверки попадания на аттрактор отображения, а время, затраченное на каждую итерацию отображения, пропорционально логарифму объема записанной информации.
Таким образом, описанная схема ассоциативной памяти для изображений обладает свойствами очень быстрого коррелятора.
3. Использование технологии детерминированного хаоса в системах автономного адаптивного управления Основная идея настоящей работы состояла в том, чтобы использовать технологию детерминированного хаоса, как способа запоминания длинных последовательностей упорядоченных данных и ассоциативного обращения к ним, в управляющей системе ААУ в качестве памяти для хранения длинных упорядоченных во времени последовательностей событий, отражающих историю
163
деятельности управляющей системы и состоящих из идентификаторов распознанных образов и совершенных действий. Требовалось найти способы встраивания хаотических процессоров в состав управляющей системы ААУ, исследовать эти варианты, сравнив их с альтернативными подходами, и проверить работу системы на модельных примерах.
3.1. Возможные варианты использования хаотических процессоров в системах автономного адаптивного управления Для математического моделирования рассматриваемых систем и их сравнения с альтернативными подходами, была разработана программная реализация модуля памяти управляющей системы ААУ с интерфейсом, который позволял проводить анализ результатов моделирования, именно, запоминать необходимые объемы информации и оценивать необходимые для этого ресурсы, оценивать производительность метода, и т.д. При этом оказалось неэффективным использование таких структур, как хэш-массивы и деревья, потому что эти структуры предполагают сортировку хранимой информации. Приемлемыми свойствами, которые могут рассматриваться как альтернатива хаотическому процессору, обладают только такие структуры, как списки. Исходя из приведенного описания структуры управляющей системы, построенной по методу ААУ, и функций ее подсистем, можно видеть, что каждая из подсистем управляющей системы может обладать адаптивными свойствами. В самом общем плане это следует уже из того, что естественная нервная система построена на «элементной базе» нервных клеток, а каждая нервная клетка обладает адаптивными свойствами – она способна накапливать статистическую информацию в своих синапсах и изменять свое функционирование соответствующим образом. Разрабатывая управляющую систему, мы также стремимся каждую ее подсистему сделать адаптивной. Тем не менее, можно указать основные подсистемы, в которых в первую очередь требуется запоминание последовательных данных по предыстории процесса управления и анализ этих данных для их автоматической классификации (кластеризации, формирования образов) и распознавания. Это подсистемы ФРО и БЗ. Рассмотрим оба варианта подробнее.
3.2. Система формирования и распознавания образов В подсистеме ФРО должны автоматически выделяться повторяющиеся пространственно-временные фрагменты во входной информации, и, при их обнаружении, формироваться в виде отдельных объектов – образов, записываемых в память образов. Сформированные образы должны этой же подсистемой ФРО распознаваться в текущей входной информации ассоциативным (в указанном смысле) способом. Чем более протяженными могут 164
быть прообразы формируемых и распознаваемых образов, тем интереснее свойства управляющей системы. Поэтому подсистема ФРО является местом, где применение хаотического процессора целесообразно. В случае построения модуля ФРО на базе хаотического процессора управляющая система получает возможность формировать образы более длинных закономерных цепочек сигналов, повторяющихся в потоке сенсорной информации. Изначально умея распознавать элементарные образы, система ФРО, обрабатывая последовательности неоднократно встречающихся последовательностей элементарных образов, может формировать образы более высокого порядка.
3.3. База знаний Подсистема БЗ фактически является частью подсистемы ФРО, ее можно рассматривать как отдельную подсистему только с той точки зрения, что особо следует выделять образы, прообраз которых состоит из трех частей, упорядоченных во времени: «образ начального состояния; образ действия; образ результирующего состояния». Такие составные образы являются, по сути, элементами знания, поскольку позволяют осуществлять управление. Такой образ является составным, так как состоит из трех частей, однако каждая из его частей может представлять собой образ как угодно протяженной последовательности событий. Отсюда следует актуальность придания базе знаний свойств, присущих хаотическому процессору. В целях исследования эффективности применения технологии динамического хаоса, была реализована управляющая система, в которой поток образов поступал в подсистему БЗ через модуль хаотического процессора, обеспечивающий работу подсистемы ФРО.
3.4. Модель окружающей среды Очевидно, что универсальную систему управления построить невозможно, и для каждого конкретного приложения существуют свои наиболее эффективные методы обработки информации. Эти соображения относятся как к системе управления в целом, так и к каждой ее подсистеме в отдельности. Нами для исследования системы был выбран модельный пример, представляющий собой некоторое пространство - лабиринт со случайно расположенными в нем объектами. В расположении объектов встречаются неоднократно повторяющиеся ситуации. По лабиринту движется робот, наблюдающий объекты и получающий при этом определенные вознаграждения или наказания. Лабиринт был представлен сетевой структурой, в которой содержание узлов (объектов, или символов) и соединительных связей (отрезков дороги) не были заданы жестко. Содержание узла представляет собой выборку M из N элементарных объектов, которые априори умеет распознавать система ФРО. Каждый из объектов имеет определенную ценность (вес), которые определены для каждого из объектов. Управляющая система может считывать содержание 165
узла, и выбирать одну из возможных связей этого узла для перехода к следующему узлу. Связи между узлами на языке системы управления выбираются (активизируются) одним из действий (“вверх”, “вперед”, “вниз”, “влево”, и т.д.). Поток информации от модели внешней среды в режиме обучения имеет следующий вид упорядоченных во времени событий:
Oi1,Oi2,…OiM,AiO(i+1)1,O(i+1)2…O(i+1)MA(i+1),…, где Oij – распознавание объекта, находящегося в текущем узле, а Ai – действиепереход к следующему узлу (в режиме управления действия Ai генерируются управляющей системой, точнее ее системой принятия решений, опирающуюся на базу знаний). Как уже отмечалось, в принятой нами модели среды отсутствует жесткость в определении связей и наполнении узлов лабиринта, т.е. выбор очередного объекта Oi может опираться либо на генератор случайных чисел, либо на правила, заданные априори. При описании модели среды задается Rn правил, которые определяются информационной строчкой образов/действий Akj ( k = 1..Rn, j = 1..Lk ) и числом Ck ( k = 1..Rn ) - минимальным числом совпадений, которые должны произойти, чтобы правило вступило в силу. Строчка Akj (k = 1..Ck) должна быть уникальна для каждого правила. Алгоритм выглядит следующим образом: 1 Если есть активные правила, то возвращается следующий элемент информационной строчки этого правила. Если выбранный элемент оказывается последним в строчке, то правило становится пассивным. 2 Если активных правил нет, то просматривается k-ое (k = 1..Rn) правило и сравнивается предыстория (последние Ck элементов, возвращенные окружающей средой) с информационной строчкой Akj ( j = 1..Ck ). 3 Если совпадений нет, то следующий образ/действие выбирается случайно. 4 Если найдено совпадение ровно с одним (k-ым) правилом, то следующим символом будет AkCk+1 -ый элемент строчки правила, которое становится активным. Использование технологий детерминированного хаоса в выбранном контексте управления при определенных условиях на M, N, Сkmin (минимальная длина префикса правил), Rn может оказаться более или менее эффективным. Первый вывод, который можно сделать, состоит в том, что чем больше объектов характеризует каждый узел и чем более уникальны эти узлы, тем более оправданной может оказаться рассматриваемая технология.
Пример модели окружающей среды: Объекты: APPLE (A), BAT(B), CANDLE(C), DIAMNOD(D),EMERALD(E)
Оценки: APPLE 166
1
BAT
-1
Рассмотрим полученные зависимости более подробно.
CANDLE
0
4.1. Время записи
DIAMOND
5
EMERALD
4
Во всех четырех рассматриваемых случаях время, необходимое на запись новых паттернов хаотическим процессором, во много раз превышало время добавлении информации в несортированный список. Общая тенденция роста времени от объема записанной информации выглядит следующим образом (рис 7.):
Возможные действия (связи):
Tsv(Nsv)
RIGHT, LEFT, FORTH Правила:
70000
APPLE BAT LEFT DIAMOND EMERALD, Ck = 3
60000
APPLE BAT RIGHT CANDLE APPLE, Ck = 3
50000 Tsv, ms
4. Результаты математического моделирования Компьютерное моделирование системы показало, что управляющая система способна обнаруживать и запоминать повторяющиеся фрагменты лабиринта, затем распознавать их при встрече, причем распознавать до того, как они заканчиваются, и когда еще можно принять решение о том или другом варианте продолжения пути, и выбирать то продолжение пути, которое способно дать большее вознаграждение. Построенные программные структуры позволили провести сравнение систем управления, использующих память на технологиях детерминированного хаоса, и память в виде списков. Учитывались следующие динамические характеристики:
Vmem(Nsaved) - объем памяти, необходимый для хранения записанной информации,
ts(Nsaved) - зависимость накопленной информации,
tr(Nsaved, Lsubstr) - зависимость времени воспроизведения от объема накопленной информации и от длины подстроки запроса,
pr(Nsaved, Lsubstr) - вероятность воспроизведения полного образа по его части, где Nsaved – число сохраненных паттернов,
Lsubstr – длина подстроки запроса на воспроизведение паттерна.
времени
запоминания
от
167
Tsv(L)
30000
Tsv(C)
20000 10000 0 0
100
200
300
400
500
600
Nsv, единицы
Рис. 7. Зависимость времени записи от числа записанных паттернов. Здесь Tsv (C) – время записи на хаотический процессор, Tsv (L) – время записи в память-список, Nsv – количество сохраненных паттернов.
объема
Для сравнения были рассмотрены случаи с различными значениями параметров N - размера входного алфавита, и M - максимальной длины паттерна. Разработанные системы исследовались на описанном выше модельном примере с лабиринтом. Вычисления проводились на PC Celeron 350, 192MB ОЗУ.
40000
Экспоненциальный рост времени записи хаотическим процессором объясняется тем, что информация должна быть определенным образом структурирована – переведена из машинного формата (линейная последовательность байт) в формат одномерного отображения, предварительно пройдя процедуру ортогонализации, которая является весьма трудоемкой. Отсюда следует, что время записи во многом определяется тем, как именно представляется одномерное отображение в памяти компьютера. Поиск более оптимальных форм этого представления является предметом дальнейших исследований. 168
4.2. Объем памяти
4.3. Время воспроизведения
Графики зависимости объема памяти от количества записанных паттернов (рис. 8) в рассматриваемых случаях тоже были принципиально похожи друг на друга:
Важным условием, благодаря которому мы отказались от использования упорядоченных структур хранения информации, в нашем сравнении является ассоциативность памяти: то есть мы должны уметь вспомнить паттерн целиком, располагая лишь его частью, и эта часть не обязательно должна быть его началом. Рассмотрим отдельно графики зависимости времени воспроизведения паттерна хаотическим процессором и хранилищем, основанном на списках (рис 9, 10).
35000
1400
30000
1200
Lsub=2(L) Lsub=4(L) Lsub=7(L) Lsub=10(L) Lsub=13(L) Lsub=16(L) Lsub=19(L) Lsub=22(L) Lsub=25(L)
1000
25000 Vmem(C) Vmem(L)
20000
800
Tr, ms
Vmem, байты
40000
600
15000
400
10000 200
5000 0 0
0 0
100
200
300
400
500
100
200
300
400
500
600
Nsv, единицы
600
Nsv, единицы
169
800 700 Lsub=2(C) 600
Lsub=4(C) Lsub=7(C)
500 Tr, ms
Рис. 8. Зависимость объема памяти от числа записанных паттернов. Здесь Vmem (C) – это объем в случае записи на хаотический процессор, Vmem (L) – это объем памяти при записи на память-список Объем памяти, необходимый для сохранения K паттернов в списке линейно зависит от K и средней длины паттерна, то есть на графике он выглядит как прямая линия. В случае хаотического процессора рост необходимой памяти в начале (при небольшом количестве записанной информации) идет более круто, чем линейная зависимость. Но поскольку в процессе преобразования информации к виду одномерного отображения происходит ее кодирование (повторяющиеся части паттернов заменяются на новые элементы алфавита - на один символ), то вскоре рост объема памяти становится медленнее линейной зависимости. Оговоримся, что здесь под объемом памяти мы имеем ввиду те ресурсы памяти, которые необходимы для воспроизведения информации. Для записи новой информации используется большее количество ресурсов, минимальный объем которых примерно равен всему объему записанной ранее информации. Такие затраты связаны с необходимостью кодирования информации с добавлением почти каждого слова (фактически перекодирование происходит каждый раз, когда увеличивается размер алфавита).
Рис. 9. Списки. Зависимость времени восстановления паттерна по его части. Tr – время воспроизведения паттерна.
Lsub=10(C)
400
Lsub=13(C) Lsub=16(C)
300
Lsub=19(C) Lsub=22(C)
200
Lsub=25(C) 100 0 0
100
200
300
400
500
600
Nsv, единицы
Рис.
10.
Хаотический процессор. Зависимость времени восстановления паттерна по его части.
Названия графиков Lsub=XX(Y) говорят о длине подстрок, по которым воспроизводились паттерны (XX = длина подстроки), и используемом 170
хранилище информации ( Y == C – хаотический процессор, Y == L – список). Зависимости времени извлечения информации из списка линейно зависит от объема записной информации (что хорошо согласуется с теорией: время поиска прямо пропорционально времени поиска подстроки в одной строке и количеству строк в хранилище), а время извлечения информации из хаотического процессора заметно зависит лишь от длины подстроки, по которой мы хотим найти целый паттерн.
1.2 1
Lsub=2(L) Lsub=4(L)
0.8
Lsub=7(L) Lsub=10(L)
0.6 Pr
4.4. Достоверность
Lsub=16(L) Lsub=19(L)
0.2
Lsub=22(L) Lsub=25(L)
0 0
100
200
300
400
500
600
-0.2 Nsv, единицы
Рис. 11. Списки. Достоверность восстановления паттерна по его части.
1.2 1 Lsub=2(C) Lsub=4(C)
0.8
Lsub=7(C) Lsub=10(C)
0.6 Pr
Время воспроизведения информации – это лишь одна составляющая эффективности использования того или иного хранилища данных. Другой составляющей является достоверность воспроизводимой информации (см рис 11, 12). Достоверность определялась следующим образом: выбирался один из сохраненных паттернов. На вход памяти подавалась подстрока этого паттерна произвольной длины и паттерн, получаемый на выходе, сравнивался с исходным. В случае их совпадения испытание считалось успешным. Доля, которую составляют успешные испытания от проводимых испытаний, мы и называем достоверностью. В данном случае число проводимых испытаний составляло 1000, и длины подстрок выбирались равными 2, 4, 7, 10, 13, 16, 19, 22 и 25. Для памяти в виде списка достоверность строго равна единице в том случае, если длина подстроки на входе оказывается больше максимальной длины подстроки, встречающейся одновременно хотя бы в паре записанных паттернов (Lsubmax). Для хаотического процессора меньшая достоверность оказывается своеобразной платой за высокую скорость воспроизведения. Чтобы результат оказался достоверным на 100%, подстрока на входе должна быть более длинной, чем в случае памяти-списка, поскольку информация в памяти хранится в сжатом виде. Математически строго обозначить ограничения для подстроки-запроса довольно сложно: она зависит от длины алфавита, длины запоминаемых паттернов, количества сохраненных паттернов и «похожести» запоминаемых паттернов. В общем, этот вопрос может являться темой для дальнейших исследований. Эмпирически полученные результаты показывают, что начиная с длины подстроки Lsubstr = 16, достоверность не опускается ниже 98%, а для Lsubstr >= 22 строго равна 1. То есть начиная с Nsv ~= 350, память на детерминированном хаосе оказывается более эффективной, нежели память с линейной организацией данных.
Lsub=13(L) 0.4
Lsub=13(C) 0.4
Lsub=16(C) Lsub=19(C)
0.2
Lsub=22(C) Lsub=25(C)
0 0
100
200
300
400
500
600
-0.2 Nsv, единицы
Рис. 12. Хаотический процессор. Достоверность восстановления паттерна по его части. 171
172
173
Созданная модель управляющей системы продемонстрировала свою жизнеспособность, показав умение выделять из входящего потока протяженные регулярности, заложенные в модель среды. Графики накопления веса (суммирование весов, встретившихся на пути УС образов) обученной и необученной систем выглядят следующим образом: 100 80 60 40 20 W
С использованием памяти на хаотическом процессоре была построена работоспособная модель системы ААУ. Модельный пример объекта управления и окружающей среды был описан в предыдущей главе – лабиринт, наполнение которого определялось заданными априори правилами. Система ААУ может работать в двух режимах – режим обучения и режим управления. В первом из этих режимов модуль ААУ получает от имитатора окружающей среды информацию о встречающихся объектах и о выполняемых управляющей системой действиях. В режиме управления на вход поступает лишь информация об объектах, а действия генерируются самой управляющей системой. В режиме обучения цикл управления выглядел следующим образом: 1. Данные от сенсора о текущем наблюдаемом символе поступают к датчикам. 2. Датчики воспринимают символ и передают его системе ФРО. 3. В системе ФРО накапливается информация до получения символаразделителя, после которого по накопленным данным происходит распознавание воспринятого объекта (будь то действие или объект среды). 4. Если распознанный образ – это действие, то он просто передается базе знаний, если был распознан образ объекта, то ему сопоставляется оценка, и пара {образ, оценка} передается базе знаний. 5. База знаний накапливает в себе информацию, поступающую от ФРО, в виде последовательности троек On – Ak – On+1 , где On – сложный образ, составленный из последовательности элементарных образов, пришедших на вход БЗ между действиями. 6. В БЗ встроен модуль памяти, который осуществляет распознавание и хранение цепочек образов Oi, частот их повторения, вероятности их появления и весов. В режиме управления цикл работы системы выглядит следующим образом. 1. Данные от сенсора о текущем символе поступают к датчикам. 2. Датчики воспринимают символ и передают его системе ФРО. 3. В системе ФРО накапливается информация до получения символаразделителя, после которого по накопленным данным происходит распознавание воспринятого объекта. 4. Распознанный образ передается базе знаний. 5. База знаний накапливает в себе информацию, поступающую от ФРО, и с поступлением каждого нового образа пытается распознать (спрогнозировать) образ целиком, опираясь на информацию модуля памяти. Для того чтобы убедиться в достоверности прогноза, обращения к модулю памяти происходят каждый раз, когда появляется новый образ, и если несколько раз
подряд память ответила одинаково утвердительно, сложный Oi образ считается распознанным. 6. Среди сохраненных цепочек On – Ak – On+1 ищутся цепочки, начинающиеся на Oi , и среди возможных действий выбирается то, которое приводит к образу с наибольшей вероятностью появления и наибольшим весом. Если среди сохраненных цепочек не оказалось начинающихся на Oi, то действие выбирается случайно.
0 -20
0
50000
100000
150000
200000
-40 -60 -80 -100 T,мс
Рис 13. Зависимость накопленного веса от времени. Режим Обучения. 200 150 100 W
4.5. Модель системы ААУ
50 0 0
50000
100000
150000
200000
-50 -100 T,мс
Рис 14. Зависимость накопленного веса от времени. Режим Управления. 174
Если считать, что на распознавание одного образа системой ФРО тратится время порядка 10 мс, то зависимости накопления веса от времени для различных модулей памяти будут следующими: 200 150
W
100 50 0 0
50000
100000
150000
200000
250000
300000
350000
-50 -100 Т,мс List
Chaos
Рис 15. Зависимость накопления веса от времени в случае использования различных модулей памяти.
5. Заключение В заключение коротко перечислим представленные в настоящей работе результаты. Основной результат состоит в том, что впервые было осуществлено слияние двух независимых технологи, обогащающее каждую из них, и расширяющее возможности их практического применения. Первая из технологий – это разрабатываемый авторами метод построения систем автономного адаптивного управления (ААУ) [22-37]. Вторая технология – способ использования детерминированного хаоса для запоминания больших массивов упорядоченной информации с ассоциативным способом обращения к ней, взятая нами из работ [3, 16-19]. Идея слияния состояла в следующем. Управляющая система ААУ в своей работе осуществляет запись в память последовательных во времени событий вида («образы, описывающие состояние объекта управления в предыстории текущего момента» «последнее действие, которое совершила управляющая система» «образы результирующего состояния объекта управления» «оценка качества этого результирующего состояния»). Среди этих последовательностей отыскиваются неслучайные последовательности, которые переписываются в базу знаний управляющей системы. При принятии решения управляющая система в случае распознавания начала такой цепочки, анализирует возможные варианты ее продолжения, связанные с альтернативными действиями, и, используя оценки качества прогнозируемых состояний, выбирает действие, наиболее 175
оптимальное в текущих условиях. Очевидно, что свойства такой системы управления становятся тем более интересными и для теории и для практики, чем длиннее предыстория, характеризующая текущее состояние объекта, которую может проанализировать управляющая система, и чем дальше в будущее простирается прогноз, который может сделать управляющая система, принимая решение. Однако организация памяти, способной запоминать длинные цепочки событий, является проблемой. Так ранее системы ААУ, которые разрабатывались авторами, могли работать с предысторией всего в несколько тактов дискретного времени, и прогнозировать всего на один-два такта вперед. При этом память системы была построена в виде массивов, либо в виде специальной многослойной нейроноподобной сети. Несмотря на то, что возможности нейросетевого подхода далеко не исчерпаны, мы искали способ радикального продвижения в этой области. В технологии детерминированного хаоса авторы увидели возможность организации памяти для хранения упорядоченных последовательностей данных, длина которых может измеряться величиной в несколько порядков. Авторам удалось применить технологию детерминированного хаоса для построения памяти управляющей системы ААУ, играющей роль базы знаний. Это позволило управляющей системе автоматически выявлять протяженные во времени закономерности событий, составляющие как предысторию совершаемого действия, так и его последствия, в случае, если таковые действительно имеются в той среде, в которой действует объект управления. Это и составляет основной результат настоящей работы. Для проверки свойств такой управляющей системы был разработан модельный пример, представляющий собой робота, движущегося в пространстве лабиринте, состоящем из последовательностей наблюдаемых символов, в котором встречаются закономерные длинные повторяющиеся, фрагменты. Показано, что робот может адаптироваться к таким фрагментам, т.е. при встрече с ними узнавать их и выбирать наиболее выгодные варианты продолжения своего пути на основе обоснованного прогнозирования. Среди частных полученных результатов, назовем следующие. Показано, что динамические характеристики модуля памяти, построенного на технологии детерминированного хаоса, являются приемлемыми для практического использования. Высокая скорость воспроизведения информации и ее кодирование, состоящее в извлечении из входного потока повторяющихся паттернов, позволяют эффективно использовать его в системах ААУ, где он может выполнять как функции системы ФРО, так и функции базы знаний. Недостатки, связанные с относительно большим временем запоминания новой информации, выглядят приемлемыми, поскольку они проявляются лишь на этапе обучения, менее критичном ко времени, чем режим управления. Тем не менее, проблема поиска более эффективного метода кодирования информации с целью 176
уменьшения времени записи новой информации, является актуальной и может стать темой дальнейших исследований. Возможности построения систем ААУ с использованием подсистем памяти и распознавания на основе технологий детерминированного хаоса, расширяют сферу практического использования таких систем. Существует обширное количество задач, связанных с анализом длинных цепочек входной информации. В частности, применение таких систем возможно в химии для анализа спектральных паттернов, в анализе временных рядов, эргономике и психологии для анализа паттернов поведения человека, при управлении различными техническими системами и технологическими процессами. С другой стороны, на наш взгляд, полученные в настоящей работе результаты могут расширить направления развития теории систем детерминированного хаоса, поскольку показывают возможности построения на его основе систем искусственного интеллекта, именно, бионических систем управления, имитирующих естественные нервные системы.
6. Направления дальнейших исследований Как отмечалось выше, настоящая работа представляет лишь начальные результаты исследования в данном направлении. В дальнейших исследованиях планируется рассмотреть следующие аспекты. 1. Исследовать возможности реализации данной технологии в системах ААУ в других контекстах. 2. Исследовать возможности реализации более оптимальных форм хранения информации для хаотических процессоров с целью улучшения их динамических характеристик 3. Исследовать теоретические ограничения применимости хаотических процессоров, принимая во внимания такие параметры, как длина подстрокизапроса, длина алфавита, длина запоминаемых паттернов, количество сохраненных паттернов и степень «похожести» запоминаемых паттернов и др.
6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Литература 1.
Artificial Neural Networks: Concepts and Theory, IEEE Computer Society Press, 1992. 2. Ф.Уоссермен, Нейрокомпьютерная техника, М., Мир, 1992. 3. Ю.В. Андреев, А.С. Дмитриев, Д.А. Куминов – Хаотические процессоры – Москва. Успехи современной радиоэлектроники, N10, 1997 4. Осовец С.М., Гинзбург Д.А. Груфинкель В.С, Зенков Л.Р., Латаш Л.П, Малкин В.Б., Мельничук П.В., Пастернак Е.Б. Электрическая активность мозга: механизмы и интерпретация. - УФН, 1983, т. 141, № 1, с.103-150 5. Rapp P.E., Zimmerman I.D., Albano A.M., Deguzman G.C., Greenbaum N.N. Dynamics of spontaneous neural activity in the simian cortex: the dimension of chaos neurons. - Phsy Lett. A, 1985, vol. 110, no.6, p335-338 177
20. 21. 22. 23.
178
Bablyoantz A., Salazar J.M., and Nicolis G. Evidence of chaotyc dynamicsof brain activity during the sleep cycle. - Phys. Lett. A. 1985, vol 132, pp 101-106 Bablyoantz A., Destexhe A. Low-dimensional chaos in an instance of epilepsy. Proc. Natl. Acad. Sci. USA 1986, vol. 83, pp. 3515-3517 Destexhe A., Sepulchre J.A., and Babyloyantz A. A comparative study of the experimental quantification of deterministic chaos. - Phys. Lett. 1988, vol. 132, pp 101-106 Bablyoantz A., Destexhe A. - in: Temporal Disorder in Human Oscillatory Systems. Springer Series in Syenrgetics, no. 36, Eds. Rensing L., Van der Heiden U., and Mackey M.C. Berlin. Springer, 1987, p 48 Шарковский А.Н., Майстренко Ю.Л., Романенко Е.Ю. Разностные уравнения и их приложения. - Киев: Наука.думка, 1986 Шарковский А.Н., Коляда С.Ф., Сивак А.Г., Федоренко В.В. Динамика одномерных отображений. - Киев: Наукова думка, 1989 Procaccia I. Universalities in Condensed Matter. - Proc Phys., vol. 32, Ed. Jullien R., Springer, 1988, p 213 Weigrinch W. and Tennekes H. On the information flow for one-dimensional maps. – Phsy. Lett. A, 1990, vol. 144, no 3 Шустер Г. Детерминированный хаос. Введение. – М: Мир, 1988 Atmanspacher H., Scheingraber H. Global scaling properties of the chaotic attractor reconstructed from the experimental data. – Phys. Rev. A, 1988, vol. 37, pp 1314-1322 Дмитриев В.А. Запись и восстановление информации в одномерных динамических системах. – Радиотехника и электроника. 1991, т. 36, N1, с101-108 Dmitriev A.S., Panas A.L., and Strakov S.O. Storing and recognition information based on stable cycles of one-dimensional maps. – Phys. Lett. A., 1991, vol.155, pp 494-499 Andreev Yu.V., Dmitriev A.S. and Starkov S.O. Information processing in 1-D systems with chaos. – IEEE Transaction on circuit and systems, 1997, vol. 44, pp. 21-28 Андреев Ю.В., Бельский Ю.Л., Дмитриев А.С. Запись и восстановление информации с использованием устойчивых циклов двумерных и многомерных отображений. – Радиотехника и электроника, 1994, т.39, с.114-123 Т. Кормен, Ч. Лейзерсон, Р. Ривест – Алгоритмы. Построение и анализ – МЦНМО, Москва, 1999. Д.А. Стpабыкин, А.А. Жданов. Адаптация диалога в цифровых измерительных приборах со встроенными микроЭВМ. Депониp. ЦHИИТЭИ пpибоpостpоения N4108-ИР88 от 23.02.88. 7 стp. Жданов А.А. О подходе к моделированию управляемых объектов. Пpепpинт ВЦ РАH СССР, М., 1991. Zhdanov A.A.. Application of Pattern Recognition Procedure to the Acquisition and Use of Data in Control.// Pattern Recognition and Image Analisis vol.2, N2,1992. (ISSN: 1054-6618).
24. Zhdanov A.A.. A principle of Pattern Formation and Recognition.// Pattern Recognition and Image Analysis vol.2, N3,1992. (ISSN: 1054-6618). 25. Жданов А.А. Об одном имитационном подходе к адаптивному управлению. Сб. "Вопросы кибернетики". Научный совет по комплексной проблеме "Кибернетика" РАН. Вып. 2. М., 1996. 26. Жданов А. А. Формальная модель нейрона и нейросети в методологии автономного адаптивного управления. Сб. "Вопросы кибернетики". Научный совет по комплексной проблеме "Кибернетика" РАН. Вып. 3. М., 1997. 27. Жданов А.А. О понятии автономного искусственного интеллекта // Сб. научн. тр. Искусственный интеллект в технических системах. - М.: Гос.ИФТП. 1997. 28. Zhdanov A. A. About an Autonomous Adaptive Control Methodology. ISIC/CIRA/(ISAS'98), NIST, Gaithersburg, Maryland. September 14-17, 1998. 29. Zhdanov A. A. The Mathematical Models of Neuron and Neural Network in Autonomous Adaptive Control Methodology. WCCI’98(IJCNN’98), IEEE World Congress on Computational Intelligence, Anchorage, Alaska, May 4-9, 1998. 30. Жданов А. А., Норкин Н. А., Гуриев М. А. Некоторые практические приложения метода автономного адаптивного управления // Сб. научн. тр. Искусственный интеллект в технических системах. Вып. 19.- М.: Гос.ИФТП. 1998. 31. Жданов А. А., Винокуров А. Н. Система проектирования и исследования нейронных сетей СПИНС в методологии автономного адаптивного управления // Сб. научн. тр. Всероссийской научн.-техн. конференции Нейроинформатика-99, ч. 1. - М.: МИФИ. 1999. 32. Рядовиков А. В., Жданов А. А., О некоторых формальных моделях нейронов. // Сб. научн. тр. Всероссийской научн.-техн. конференции Нейроинформатика-99, ч. 1. - М.: МИФИ. 1999. 33. Жданов А. А., Арсеньев С.В. О некоторых приложениях принципа автономного адаптивного управления // Сб. научн. тр. Всероссийской научн.-техн. конференции Нейроинформатика-99, ч. 3. - М.: МИФИ. 1999. 34. Жданов А. А., Винокуров А. Н. О нейросетевом методе Автономного адаптивного управления, Сб. докл. V Всероссийской конференции Нейрокомпьютеры и их применение (НКП-99). М., 17-19 февраля 1999. 35. http://www.ispras.ru/~zhdanov/ 36. Жданов А. А., Метод автономного адаптивного управления // Известия Академии Наук. Теория и системы управления, 1999, № 5, с. 127-134 37. Жданов А.А., Арсеньев С.В., Половников В.А. Об одной методологии автономного адаптивного управления. Труды института системного программирования РАН. 1999. Том 1. М.: Биоинформсервис, 2000.- С. 66-83. 38. Жданов А.А., Беляев Б.Б., Мамаев В.В. Использование принципа автономного адаптивного управления в системе угловой стабилизации космического аппарата «Спектр РГ» // Сб. научн. тр. Информационная бионика и моделирование. - М.: ГосИФТП, 1955. – С. 87 - 114. 179
радиоволн помехи могут возникать и между передатчиками, работающими на разных частотах. К настоящему времени разработан ряд теоретических и эмпирических моделей распространения радиоволн над поверхностью земли [1,2], на которых основаны практически значимые алгоритмы предсказания величины уровня радиосигнала, достигающего различных точек местности. Все модели в большей или меньшей степени используют информацию о рельефе земной поверхности.
Применение геоинформационных технологий к автоматизированному проектированию систем радиосвязи
Таким образом, при планировании радиосвязи требуются различные виды географической информации, и значит, компьютерная система автоматизированного проектирования должна быть интегрирована с достаточно мощной географической информационной системой (ГИС).
К.П. Голиков Аннотация. В работе рассматриваются некоторые аспекты применения геоинформационных технологий в задачах автоматизированного проектирования систем радиосвязи. Приводятся структура данных и алгоритм пространственной интерполяции для построения цифровой модели рельефа земной поверхности по топографической карте изолиний высот.
1. Введение Системы радиосвязи - одна из самых быстро развивающихся отраслей промышленности в мире. К таким системам относятся и более современные системы сотовой и пейджинговой связи, и системы радиовещания и телевидения, и более традиционные сети радио и радиорелейной связи. Промышленно развитые страны тратят миллионы долларов ежегодно на развитие систем радиосвязи, поэтому необычайно важной становится проблема эффективного проектирования таких систем. Основная цель любой системы планирования радиосвязи – обеспечить определенный уровень полезного сигнала, получаемого приемником в заданной точке местности. Обычно эта цель достигается подходящим выбором рабочих частот и мест расположения передатчиков. Точки с допустимыми значениями уровня принимаемого сигнала образуют на местности зону обслуживания (покрытия) передатчика. Следует отметить, что для современных систем радиосвязи оптимизация зоны обслуживания вовсе не означает, что эта зона должна быть как можно более обширной. Дефицит свободных радиочастот приводит к тому, что одна и та же рабочая частота используется разными передатчиками, находящимися на достаточном удалении друг от друга. Зоны обслуживания таких передатчиков не должны пересекаться. В более общей постановке еще одна задача планирования радиосвязи состоит в оценке взаимных помех между передатчиками новой и существующих систем связи. В силу некоторых особенностей интерференции 181
Прежде всего, ГИС обеспечивает проектировщику работу с цифровой топографической картой местности. Цифровая карта позволяет произвести общую оценку территории, на которой разворачивается система радиосвязи. На цифровой карте в интерактивном режиме выполняется размещение передатчиков, отображаются и оцениваются зоны обслуживания, “затенения” и радиопомех. Для более простых систем радио и радиорелейной связи, со стационарно расположенными приемно-передающими станциями, на карте обозначаются трассы соединений, выбираются места установки ретрансляторов. Цифровая карта с нанесенными на нее элементами радио обстановки служит основой для получения твердых копий выходных документов системы автоматизированного проектирования. Для расчетов распространения радиоволн необходима цифровая модель рельефа земной поверхности. Горы, холмы и другие возвышенности рельефа блокируют радиоволны, вызывая дифракцию вокруг вершин и склонов, что приводит к заметным потерям сигнала в точке приема. Большинство моделей распространения радиоволн для анализа рельефа использует профили. Профиль – это вертикальный разрез земной поверхности плоскостью, проходящей через точки размещения антенн передатчика и приемника. Наиболее точные модели кроме рельефа учитывают еще и особенности подстилающей поверхности (“clutter”). Подстилающую поверхность составляют растительный покров, застройка и водные пространства. Лесные массивы и строения рассматриваются как дополнительные препятствия на пути распространения волны. Водные пространства влияют на величину и фазу отраженного сигнала, достигающего приемника. В перспективе для планирования радиосвязи в крупных городах потребуются пространственные модели каждого здания и сооружения, а также учет отражающих и поглощающих свойств материалов, из которых они построены.
182
Далее в статье будут рассмотрены практические методы и алгоритмы для построения и анализа модели рельефа с учетом информационных потребностей автоматизированного проектирования систем радиосвязи.
2. Цифровые модели рельефа земной поверхности Цифровые модели рельефа (ЦМР) начали разрабатываться и применяться еще в 50-е годы, и с тех пор они стали важным инструментом моделирования и анализа пространственно-топографической информации. Помимо интересующих нас задач распространения радиоволн, модели рельефа широко применяются в таких областях как строительство, геология, управление ресурсами, геодезия и картография. Существуют многочисленные и разнообразные приложения таких моделей в военных целях. К настоящему времени подсистемы моделирования рельефа составляют интегральную часть многих инструментальных геоинформационных систем [3]. Для построения ЦМР используются три основных источника информации: оцифровка традиционных топографических карт, полевая геодезическая съемка и фотограмметрические данные, полученные методами дистанционного зондирования (аэросъемка, съемка со спутников и т.п.). Полевая геодезическая съемка и фотограмметрические методы доступны только с привлечением специализированных организаций, обладающих необходимыми исходными данными, обученным персоналом и весьма дорогостоящим профессиональным оборудованием. Поэтому, несмотря на значительный прогресс в развитии фотограмметрических методов, позволяющих получать наиболее точные ЦМР регионального покрытия, самым распространенным и доступным к настоящему времени источником для построения моделей рельефа остаются топографические карты. На топографических картах рельеф местности изображается при помощи горизонталей. Горизонталь - это изолиния точек равной высоты над уровнем моря. Кроме того, на картах изображаются точки локальных максимумов и минимумов высот с цифровыми отметками. Для более полной характеристики рельефа используются специальные обозначения хребтов, обрывов и других особенностей формы. Важную роль играет изображение гидрографии, поскольку русла рек и ложа водоемов располагаются в углублениях рельефа и характеризуют естественный уклон поверхности. Ввод информации с топографических карт чаще всего выполняется при помощи растровых сканеров. Затем полученный цифровой образ векторизуется. Векторизация означает преобразование растрового изображения в набор векторных графических примитивов. Для карты рельефа этот набор обычно состоит из точек и ломаных. После векторизации требуется значительный объем интерактивного редактирования для устранения дефектов. Дефекты могут быть 183
вызваны как ошибками векторизации, так и рядом соглашений, принятых при составлении исходных карт. Например, немалую проблему составляет устранение разрывов линий, выполненных для размещения надписей и условных обозначений. На завершающем этапе примитивам приписываются значения высот. Полученная в результате цифровая контурная карта или, как ее еще называют, гипсография (hypsography) служит исходным материалом для построения ЦМР. Наряду с другими слоями цифровой карты местности, гипсографические данные могут быть представлены в стандартных форматах обмена графической информацией (DXF, DGN и др.). Основная проблема, возникающая при построении ЦМР, это интерполяция высот в промежутках между горизонталями. В общем случае задача интерполирования сводится к построению непрерывной и достаточно гладкой поверхности по линиям равных значений. Однозначного решения эта задача не имеет, в связи с чем разработано множество разных методов пространственной интерполяции [5,6,7] . Идеального метода не существует. Каждый метод имеет свои ограничения и ориентирован на доступные ресурсы вычислительной системы. Среди методов пространственной интерполяции на картах изолиний особое место занимают градиентные методы. Они отличаются высокой эффективностью, имеют простую реализацию и обеспечивают хорошее качество представления поверхности, выявляя такие особенности формы рельефа как хребты и долины. В следующих параграфах мы рассмотрим алгоритм интерполяции, развивающий идею одного из таких методов, предложенного в работе [8] и известного как метод последовательного наискорейшего спуска.
2.1. Структура цифровой модели рельефа для анализа распространения радиоволн Для анализа распространения радиоволн обычно используются матричные (растровые) модели рельефа. Такая модель подразумевает, что территория разбивается на ячейки равного размера. Каждой ячейке сопоставляется элемент прямоугольной матрицы. Значение элемента – высота земной поверхности над уровнем моря. Важно отметить, что необходимое пространственное разрешение модели существенно зависит от частоты радиосигнала. Например, если на частоте 900МГц для достаточно точного предсказания дифракционных потерь на пути распространения волны требуется размер матричного элемента порядка 80м и разрешение по высоте 8м, то на частоте 2300МГц эти величины составляют соответственно 30м и 3м. В [4] приводится правило приблизительной оценки, в силу которого допустимый размер матричного элемента составляет 250 длин 184
волны, а разрешение по высоте 25 длин волны. Для городских территорий с плотной застройкой требуются модели с еще более высоким разрешением. Для удобства дальнейшего изложения будем считать, что модель рельефа покрывает сравнительно небольшую территорию, которая целиком отображается на одну плоскость картографической проекции. Тогда ЦМР можно представить как прямоугольную матрицу квадратных ячеек – пикселов, лежащую в этой плоскости. Координатами пиксела на поверхности земли будем считать географические координаты его центральной точки. Высоту пиксела определим как высоту земной поверхности в некоторой точке, лежащей внутри пиксела. С точностью до метра высоту над уровнем моря в любой точке суши земного шара можно представить целым числом в диапазоне от –407 до 8752 метров. Вне этого диапазона выберем специальное значение NIL, которое показывает, что пиксел “пустой”, т.е. высота для него не определена. В силу принятых соглашений ЦМР имеет структуру двумерной матрицы целых чисел. Такую модель можно интерпретировать еще и как растр - целочисленную решетку точек, расположенных по центру ячеек матрицы. На дискретной модельной плоскости определим правостороннюю систему координат так, чтобы левый нижний пиксел матрицы имел координаты (0,0). Заметим, что для реальных задач планирования радиосвязи требуются матрицы большого размера. Например, модель рельефа, покрывающая территорию 120x120 км с разрешением 30м, имеет размеры 4000x4000 пикселов и занимает более 30Мб памяти. Типовая задача при моделировании распространения земной волны включает анализ профиля прямолинейной трассы между антеннами передатчика и приемника. Для стационарно расположенных антенн количество профилей невелико и анализ с высокой точностью может быть выполнен за короткое время. Однако при планировании систем радиовещания, телевидения и мобильной связи необходимо построить большое количество профилей. Теоретически требуется трассировка пути распространения сигнала от передатчика к любой точке местности, где может находиться приемник. На практике для прогнозирования зоны обслуживания обычно рассматривается семейство радиальных трасс, исходящих из точки размещения передатчика. Для получения достаточно точного прогноза требуется очень плотная сетка таких трасс. Проведенные нами эксперименты показали, что традиционные способы размещения матрицы, например по строкам, дают очень низкую эффективность доступа к базе данных модели. Существенно лучшие характеристики времени доступа получаются, если в структуру модели ввести дополнительный логический уровень, разбив растр на прямоугольные блоки сравнительно небольшого размера. Такая структура в большей степени учитывает пространственную когерентность извлекаемых из модели данных при построении профилей прямолинейных трасс. Среднее количество ячеек, пересекаемых трассой в одном блоке, мало зависит от направления трассы. 185
Кроме того, две соседние радиальные трассы при круговом сканировании модели лежат в практически совпадающих цепочках блоков. Все это хорошо согласуется со страничным механизмом доступа виртуальной памяти.
Рис. 1 Блочная структура хорошо “работает” в интерактивных процедурах визуализации модели, позволяя проводить достаточно естественную генерализацию изображения рельефа. На рис.1 приведено детальное изображение рельефа, в котором интенсивность тона определяется значением высоты в каждой ячейке модели. На рис.2 показано обзорное изображение рельефа в мелком масштабе. Интенсивность тона определяется максимальным значением высоты в блоке. Хорошо заметны наиболее возвышенные участки местности, представляющие наибольший интерес для размещения передатчиков. С другой стороны, при пересечении таких участков возможны наибольшие потери радиосигнала. Белым цветом выделен участок с максимальным значением высоты по всей области определения модели. 186
Рис. 2
2.2. Алгоритм пространственной интерполяции при построении ЦМР Мы будем предполагать, что цифровая контурная карта рельефа состоит из векторных примитивов двух типов – ломаных и точек. Ломаные соответствуют линиям равной высоты, точки – локальным отметкам высот. Каждому примитиву приписана z-координата – значение высоты над уровнем моря. Модель рельефа формируется в два этапа. На первом этапе создается “пустая“ матрица и выполняется растеризация векторных примитивов контурной карты. Локальная отметка высоты инициирует значение одной, содержащей ее ячейки матрицы. Ломаная раскладывается в 4-связную дискретную кривую [9]. Эта кривая обладает двумя важными свойствами. Во-первых, она содержит все ячейки, которые пересекает ломаная. Во-вторых, составляющие ячейки соприкасаются сторонами. Если в какую-то ячейку матрицы попадают 187
изображения двух и более примитивов контурной карты, то для нее выбирается максимальное значение высоты. На втором этапе выполняется интерполяция значений высот в незаполненных ячейках матрицы. Для решения этой задачи воспользуемся стратегией сканирующей линии. Воображаемая вертикальная линия сканирования перемещается слева направо, пересекая столбцы матрицы. В текущем столбце поочередно обрабатываются еще не заполненные ячейки. В структуре состояния алгоритма собирается информация о высоте рельефа слева от линии сканирования, которая необходима для последующих вычислений. Фактически это значения высот в предшествующем столбце матрицы, однако, если в базе данных высоты представлены в целочисленном формате, то в структуре состояния они сохраняются в формате с плавающей точкой, что позволяет избежать накапливания ошибок промежуточных вычислений. Когда линия сканирования передвинется за последний столбец матрицы, все ячейки будут заполнены значениями высот. Для вычисления высоты в точке S, находящейся в центре еще не заполненной ячейки на линии сканирования, используется метод наискорейшего спуска [8]. Мы предполагаем, что высота рельефа является непрерывной и достаточно гладкой функцией координат на поверхности Земли. Приблизительное направление градиента функции определяется поиском по четырем направлениям – вертикальному, горизонтальному и двум диагональным. Схема поиска показана на рис. 3. Точка 1 это предшествующая S точка на линии сканирования. Точки 2, 3 и 4 соседние к S точки предыдущего столбца, уже обработанного алгоритмом и сохраненного в структуре состояния сканирующей линии. Точки 5, 6, 7 и 8 определяются как центры ближайших к S заполненных ячеек матрицы. Поиск заполненных ячеек выполнятся последовательным перебором, и составляет наиболее затратную по времени фазу работы алгоритма. В качестве направления градиента принимается то направление, по которому уклон поверхности имеет наибольшую абсолютную величину. Предположим, что это направление 2-6. Тогда высота в точке S вычисляется при помощи линейной интерполяции высот в точках 2 и 6:
hS =h2 + (h6 –h2) 2,S 2,6 Здесь - евклидово расстояние между точками. Вблизи границ модели возникают ситуации, когда уклон не может быть определен ни по одному из направлений поиска. Например, в начальном положении линии сканирования не определены точки 2, 3 и 4, а в конечном положении – точки 6, 7 и 8. В этих случаях высота вычисляется как взвешенное среднее высот в тех точках, которые определены. Веса обратно пропорциональны расстояниям до этих точек. 188
3. Заключение Цифровые топографические карты и цифровые модели рельефа земной поверхности – это важнейшие компоненты базы данных для автоматизированного проектирования систем радиосвязи. Применение геоинформационных технологий позволяет использовать сложные модели распространения радиоволн для предсказания величины уровня радиосигнала в различных точках местности. Проектировщик может в интерактивном режиме проигрывать сценарии размещения узлов телекоммуникационной сети, получая результаты в наглядной графической форме с привязкой к местности. Рассмотренные в статье подходы к построению специализированной геоинформационной базы данных были реализованы в рамках совместного проекта ИСП РАН и НИИспецтехники МВД РФ по разработке системы планирования радиосвязи ОВЧ-диапазона.
Литература
Рис. 3 Для оценки качества полученных моделей мы провели ряд тестов. Специалисту было предложено вручную построить профили для случайно выбранных трасс, используя исходную топографическую карту. Для сравнения те же профили были построены автоматически по цифровой модели рельефа. Расхождения между профилями оказались в допустимых пределах, не превышая половины интервала высот между горизонталями на исходной карте.
189
1. Черенкова Е.Л., Чернышев О.В. Распространение радиоволн. М.:Радио и связь, 1984. 2. Пономарев Г.А., Куликов А.Н., Тельпуховский Е.Д. Распространение УКВ в городе. - Томск. МП “Раско”, 1991. 3. Цветков В.Я. Геоинформационные системы и технологии. - М.: ”Финансы и статистика”, 1998. 4. Kinch-James D.G. Spatial data for radio communication systems planning. – Photogrammetric Record, 14(81), April 1993. 5. Robinson G.J. The accuracy of digital elevation models derived from digitized contour data. - Photogrammetric Record, 14(83), April 1994. 6. Ушаков А.Н. Алгоритм восстановления поверхности на ЦВМ по линиям равных значений. В сб. “Вопросы кибернетики”, Вып. 38, М., 1978. 7. Яковлев А.Ф. Метод граничных сетей для представления и обработки географической информации в ЭВМ. – М.: Вычислительный центр АН СССР, 1982. 8. Leberl F.W., Olson D. Raster scanning for operational digitizing of graphical data. – Photogrammetric Engineering and Remote Sensing, Vol. 48, No. 4, April 1982. 9. Дж. Фоли, А. Вэн Дэм. Основы интерактивной машинной графики. – М.: “Мир”, 1985.
190