Содержание курса (ost.kiam.ru) • Алгоритмы композиции вычислительных объектов • Архитектура параллельных моделей • Средства программирования • Критерии качества параллельных моделей (специалист: мин стоимость, время, макс качество) • Решение на МВС (>100 процессоров) ИПМ РАН конкретных простых задач. Ноуты-WIFI • Вопросы к экзамену Представления реальной области цепочка моделей Реальная область Физическая модель Математическая модель Вычислительная модель Замена реальн ости Программно-аппаратная модель Подобие всех представлений моделей и реальной области в виде множества взаимодействующих объектов и связей между ними ПАРАЛЛЕЛЬНЫЕ ВЫЧИСЛЕНИЯ В чем проблема? Тупик традиционного подхода: Физическая область – уравнения – дискретизация – последовательная программа – последовательный процессор. Физические ограничения на скорость одного процессора. Нужна декомпозиция области и отображение на множество процессоров. Аппаратный уровень Процессоры: УУ АУ Х86 +++ + критерий эффективности ARM ++ ++ архитектуры ГРАФ. + +++ число операций / ватт Intel MIC Knight Corner cards (60 cores) (микропрограммы) Средства связи: Дерево коммутаторов Проблема – масштабируемость по количеству процессоров. Решение – согласованность скорости распространения сигналов в аппаратуре и физической среде (подобие этих двух представлений). Параллелизм на уровне команд Независимые действия: A=B+C D=E+F Зависимые действия: А=B+C D=E+A Динамический (аппаратный) и статический (компилятор) анализ программы. Процессоры – внеочередное выполнение команд. Выигрыш – 2-4 раза. Аппаратура УУ усложняется на порядок. Параллелизм на уровне процессорных ядер Многоплатные, многостоечные серверы Многоядерные кристаллы: - графические платы (примитивные ядра) – 2-3 тысячи ядер - Intel MIC (X86) – 60 (240) ядер Параллелизм на уровне программ Распараллеливание последовательных программ (алгоритмов) Очень частная и в общем случае неверная цель. 40 лет малоуспешных усилий. Основная причина – в последовательном алгоритме отсутствует явная информация о естественном параллелизме исходной физической области, привнесены лишние зависимости. Общий метод выхода из тупика – Расширить множество возможных решений – избавиться от ненужных ограничений Обязательность промежуточного последовательного алгоритма – ненужное ограничение. Последовательность – причинность Параллельность - независимость Оставить только те последовательности, которые обусловлены причинностью в физической области. Параллелизм на уровне вычислительной модели Композиция подобластей Представления реальной области цепочка моделей Реальная область Физическая модель Математическая модель Вычислительная модель Замена реальн ости Программно-аппаратная модель Подобие всех представлений моделей и реальной области в виде множества взаимодействующих объектов и связей между ними Вопросы для любого уровня представления модели • • • • • Как оформлены части модели? Адресация частей? Как оформлены связи между частями? Как создаются связи? Как используются связи? Синхронизация? ПАРАЛЛЕЛИЗМ НА РАЗНЫХ УРОВНЯХ ПРЕДСТАВЛЕНИЯ • Естественный параллелизм физической области • Параллелизм аппаратной среды • Наша задача – сохранить параллелизм физической области на промежуточных уровнях • Принцип подобия уровней • Решение – построение моделей из частей в стиле натурного моделирования ДЕКОМПОЗИЦИЯ/КОМПОЗИЦИЯ • Части – связи - взаимодействие • Декомпозиция физической области • Композиция на уровне вычислительной дискретной модели • Композиция на уровне программной модели АППАРАТНАЯ СРЕДА • Множество процессоров. • Взаимодействия: - линии связи - общая память Критерий оценки качества – подобие моделируемой физической области ПРОГРАММНЫЕ МОДЕЛИ • Процессно-ориентированная модель – множество параллельно выполняющихся процессов. Процессы взаимодействуют путем посылки сообщений друг другу. • Объектно-ориентированная модель – множество объектов, которые взаимодействуют вызывая операции друг в друге. КРИТЕРИИ СРАВНЕНИЯ Оценки сложности и качества описания компонент параллельной модели: - Частей модели - Связей между частями модели - Синхронизации взаимодействия частей /* Общая схема MPI программ */ #include<mpi.h> int main(int argc, char **argv) { int rank, size; // Инициaлизация работы с MPI MPI_Init(&argc, &argv); // Программа работы с mpi // Одинаковая для всех процессоров // Завершение работы с MPI MPI_Finalize(); return 0; } /* Пример описания частей модели */ // Определение номера процессора MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Определение количества процессоров MPI_Comm_size(MPI_COMM_WORLD, &size); if (rank == 0) { // Программа процессора #0 } else { // Программы других процессоров } /* Связи между частями модели. Посылка данных */ if (rank == 0) { // Программа процессора #0 int data_send[L]; // Отправить массив data_send на процессор #7 MPI_Send(data_senf, L, MPI_INT, 7 , 1, MPI_COMM_WORLD); } else if (rank == 7) { // Программа процессора #7 int data_resv[L]; MPI_Status status; // Принять массив длины L с любого процессора в data_resv MPI_Recv(data_resv, L, MPI_INT, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, &status); } Решетка 8 х 8 «Логическая» нумерация процессов в решетке процессоров 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 . . . 56 57 58 59 60 61 62 63 Сосед «слева», «справа», «снизу», «сверху» На внешних границах соседи отсутствуют. «Физическая» нумерация процессоров? /* Реализация связи между частями модели */ // Определение номера процессора MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Программа процессора #i // Послать сообщение соседу вниз If((rank/8)<7) {MPI_Send(data_senf, L, MPI_INT, rank+8 , mesg_id, MPI_COMM_WORLD, status); }else{ нижняя внешняя граница} Объект.операция(операнды); Подлежащее – сказуемое - дополнения /* Синхронизация */ if (rank == 0) { /* Возврат из * MPI_Barrier(MPI_COMM_WORLD) * произойдет после того, как каждый * процессор вызовет функцию барьера */ MPI_Barrier(MPI_COMM_WORLD); } else if(rank == 7) { MPI_Barrier(MPI_COMM_WORLD); } /* Синхронизация */ /* Возврат из * MPI_Barrier * произойдет после того, как каждый * процессор вызовет функцию барьера */ MPI_Barrier(MPI_COMM_WORLD); time_step = time_step+1; Доступ к данным (C++) Ifstream inData;//создаем объект типа ifstream inData.open(itoa(i), ios:in); //открываем в directory /home файл i inData.seek(100); // установить текущим 100-ый байт inData.read(buf,1000); //прочитать 1000 байтов, начиная 100-го Объектно-ориентированная модель Объектно-ориентированная модель – множество объектов, которые взаимодействуют вызывая операции друг в друге. Множество процессов, исполняющих процедуры в объектах. Соотношение между объектами и процессами – «много-много» Сеть «прозрачна» для вызовов операций Что принципиально важное отсутствует в С и Фортране ? • Любая программа (кроме простейших) строится из раздельно программируемых, но согласованных частей. Это есть и С и Фортране. • Программный код и данные бессмысленны друг без друга • В Фортране и С есть модульность по программам – главная программа + подпрограммы • В Фортране и С данные счета только в главной программе. Отсутствует модульность по данным. Нет конструкции для объекта из физической области. ОБЪЕКТ вызов ССЫЛКА: Таблица фактических номеров операций Указатель на объект связи Среда связи Описатель объекта: Таблица указателей на процедуры Указатель на данные Вход – формальный номер операции Процедура 2 Процедура N Структура данных Left.oper5(параметры) Процедура 1 Вход - фактический Номер операции ПРОЦЕСС – виртуальный процессор вызов Пуск Стоп Приоритет Т.д. ССЫЛКА: Таблица фактических номеров операций Указатель на объект связи Среда связи Описатель объекта: Таблица указателей на процедуры Указатель на данные ПУСК Стоп Приоритет Указатель на программу Счетчик команд Приоритет т.д. processA.priority(10) ДЕЙСТВИЯ С ОБЪЕКТАМИ • Описание класса -> набор процедур • Создание объекта статическое (в момент компиляции) или динамическое (в момент счета) -> объект на вызываемой стороне • Регистрация объекта в общеизвестном каталоге • Описание переменной –> ссылка на объект на вызывающей стороне • Связывание ссылки (из вызывающей программы, например, после поиска в каталоге) с объектом -> таблица номеров операций, физический адрес • Вызов операции в объекте О-О пример (Python) # Опишем 2 класса с одинаковыми интерфейсами (полиморфизм) class ExampleClassDog(): def __init__(self, _name): self.name = _name def voice(self): print "My dog is named", self.name class ExampleClassCat(): def __init__(self, _name): self.name = _name def voice(self): print "My cat is named", self.name # Создание объектов mycat = ExampleClassCat("Kitty") mydog = ExampleClassDog("Robby") # Вызов операции в объекте mycat.voice() # Вывод: My cat is named Kitty mydog.voice() # Вывод: My dog is named Robby # Передача объекта по ссылке # функция в объекте anyobj def listen(self,pet): pet.voice() # anyobj.listen(mycat) # Вывод: My cat is named Kitty anyobj.listen(mydog) # Вывод: My dog is named Robby Передача объекта как параметра вызова – главное средство установления связей между частями, распределенными по процессорам. НЕДОСТАТКИ ПРОЦЕССНООРИЕНТИРОВАННОЙ АРХИТЕКТУРЫ • Ориентация на «главная программа + подпрограммы» для оформления параллельных частей • Подмена локальных механизмов взаимодействия частей (вызов подпрограмм) на передачу сообщений • Локальность процессов , один процесс – одни данные НЕДОСТАТКИ СТАНДАРТНОЙ О-О АРХИТЕКТУРЫ • Ручное связывание созданных объектов в систему взаимодействующих объектов • Ручная синхронизация взаимодействия объектов ЧТО ДАЕТ OST Objects-Space-Time • Автоматическое связывание объектов по их координатам в пространстве • Автоматическая синхронизация взаимодействия по объектов по их локальным временам Объектно-ориетированная параллельная модель на примере системы OST (Objects-Space-Time) • Этапы создания и счета модели: - Декомпозиция физической области на части - Написание классов, реализующих поведение частей - Написание начальной программы, которая создаст все объекты модели и поместит их в файл объектов. - Счет модели: выполнение функций (процедур) в объектах, вызовы операций в соседях # Структура класса объекта class applied_object(ost.Object.Abstract): # Класс прикладного объекта def fun_1(self, ...): # Содержимое функции def fun_N(self, ...): # Содержимое функции # Функция начала вычислений def run(self): # self - аналог this в c++ self.setFinish() #-------------------------------------------------------# # Начинаем иницилизацию модели # Создаем объект иницилизации. # Сохранять модель будем в файле modelname.mod obj_init = ost.Core.Init("modelname.mod«) # Зададим класс глобальной топологии # В данном случае кольцо с 10 элементами obj_init.topology = ost.Topology.Ring(N = 10) # цикл, в котором создаются объекты модели # В примере создаются 10 объектов, для кольца for index in xrange(0,10): # Создание объекта типа applied_object app_object = obj_init.create_object( applied_object ) # объект заполняется необходимыми данными # можно задать локальную топологию объекта # В данном примере мы описываем окрестность состоящую из элементов P1,…,Pk app_object.topology = ost.topology.Neighborhood([P1,…,Pk]) # Помещаем объект в точку пространства объектов # Точка имеет координату index obj_init.topology.set(app_object, index) def run(self): # self.topology.neighbors список формальных соседей #Обращение к i-ому соседу по fun_j-ой функции self.topology.neighbors[i].link.fun_j() # При наличии синонимов использование проще # Обращение к соседу слева по fun_j-ой функции self.left.fun_j() # Вызов произойдет только при равенстве локальных времен вызывающего и вызываемого объектов # После окончания вычислений завершаем вычисления self.setFinish() # В переменной self.time хранится текущее время объекта для синхронизации # Для продвижение на шаг time_step делается запрос к монитору OST # возврат из которого произойдет только после продвижения self.setXYZT(self.time + time_step) # Функция задает интерфейс из формальных соседей # Задает синонимы и интерфейсы данного соседа def init_topology(self): # Задаем интерфейс и синоним для формального соседа i1 self.init_neighbor(i1, Class_interface_i1, "synonym_i1") ... # Задаем интерфейс и синоним для формального соседа iK self.init_neighbor(iK, Class_interface_iK, "synonym_iK") # Структура класса с функцией описания окрестности class applied_neighbr_topol(ost.Topology.Abstract): # Функция описания окрестности точки в пространстве def neighborhood(self, p): # p - набор(массив) координат, рассматриваемой точки # Возвращает массив(словарь) наборов(массивов) координат точек, которые входят в окрестность рассматриваемой точки p # с заданием синонимов "соседей" return { synonym1: [p1_x1,...,p1_xn1], ...., synonymk: [pk_x1,...,pk_xnk] } # Пример топологии Графа на основе функции описания окрестности class graph_neighbr_topol(ost.Topology.Abstract): def __init__(self): #Таблица, задающая ребра графа self.edges = { 0 : [1, 3], 1 : [0, 2, 3], 2 : [], 3 : [2] } # Функция описания окрестности вершины p # Возвращает список всех вершин, с которыми соединена данная p def neighborhood(self, p): return self.edges[p] class line_topology(ost.Topology.Abstract): #Функция описания окрестности вершины p # В случае прямой справа и слева # left и right синонимы def neighborhood(self, p): return { left : p[0] - 1, right: p[0] + 1 } # Объекты могут менять свое положение в пространстве # Получение актуального массива координат текущего объекта coord = self.topology.get_coordinates() # Изменение coord # Монитор OST изменяет координаты # только вместе с продвижением по времени self.setXYZT(self.time + time_step, coord) Примеры в небесной механике и молекулярной динамике