
- •Билет №1
- •1.Составные части и свойства распределенной системы
- •2. Удаленный сервер
- •Билет №2
- •1. Параллелизм в распределенной системе
- •2. Реализация локального сервера
- •Билет №3
- •1. Закон Амдала
- •2. Заместитель/заглушка. Компилятор midl
- •Билет №4
- •1. Ускорение решения задачи в распределенной параллельной системе
- •2. Язык idl
- •Билет №5
- •1. Последовательные операции. Параллельные операции. Число процессоров.
- •2. Назначение данных на узлы распределенной системы. Модель назначения объектов на узлы. Сокращение трафика в каналах передачи данных.
- •Билет №6
- •1. Планирование параллельной распределенной обработки данных.
- •2. Модель назначения объектов на узлы. Частоты запросов к объектам. Длины объектов. Производительность узлов. Производительность каналов передачи данных.
- •Билет №7
- •1. Параллелизм в пространстве и во времени (конвейерный параллелизм)
- •2. Среднее время обработки одного запроса. Минимизация времени
- •Многошаговое планирование на базе asap
- •Билет №8
- •1. Синхронное и асинхронное планирование.
- •2. Время обработки всех запросов к объектам. Загрузка узлов. Загрузка каналов передачи данных.
- •Билет №9
- •1. Планирование при ограничениях на ресурсы, время, достижимость
- •2. Локальный вызов процедуры. Маршалинг Локальный вызов процедуры
- •Маршалинг
- •Б илет №10
- •Стратегия планирования asap Алгоритм планирования asap (как можно раньше)
- •2. Серверы в exe.
- •Билет №11
- •1. Стратегия планирования alap
- •2. Включение и агрегирование компонентов
- •Стратегия планирования «Группировка доминирующей последовательности» (Dominant Sequence Clustering - dsc)
- •Билет №12
- •1. Стратегия спискового планирования
- •Регистрация компонента в реестре
- •Билет №13
- •1. Многошаговое планирование
- •2. Функции CoGetClassObject и DllGetClassObject и их использование
- •Билет №14
- •1. Цепочечное планирование
- •2. Интерфейс iClassFactory
- •Билет №15
- •1. Граф предшествования и граф распараллеленности операций
- •2. Фабрика класса
- •Билет №16
- •1. Свертывание графа распараллеленности операций
- •2. Использование динамической библиотеки. Экспорт функций из библиотеки. Загрузка и выгрузка dll
- •Билет №17
- •1. Синтез последовательно параллельного плана
- •2. Динамическая компоновка. Библиотеки dll. Создание динамической библиотеки
- •Билет №18
- •1. Модель разнородной распределенной системы
- •2. Управление временем жизни компонента. Подсчет ссылок
- •Билет №19
- •1. Сведение планирования к задаче целочисленного линейного программирования
- •2. Запрос интерфейса. Интерфейс iUnknown. Реализация интерфейса
- •Билет №20
- •1. Задача минимизации ресурсов при заданном времени реализации плана
- •2. Таблица виртуальных функций
- •Билет №21
- •1. Целочисленное линейное программирование. Пример. Целевая функция. Система ограничений
- •Многошаговое планирование на базе asap
- •Билет №22
- •1. Планирование выполнения графа задач на узлах распределенной системы с учетом обмена данными
- •2. Теория интерфейсов
- •Неизменность интерфейсов
- •Билет №23
- •1. Граф задач. Назначение задач на процессоры. Обмен данными. План решения задач на каждом процессоре. Планирование выполнения графа задач на узлах распределенной системы с учетом обмена данными
- •Планирование графа задач
- •2. Языки и инструменты программирования распределенной обработки данных.
- •Билет №24
- •1. Стратегии планирования на графе задач. Планирование графа задач
- •2. Процессы и потоки. Многопоточные приложения. Модель многопоточных приложений
- •Билет №25
- •1. Стратегия планирования «Наиболее ранняя задача первая» (Earliest Task First - etf). Стратегия планирования «Наиболее ранняя задача первая» (Earliest Task First - etf)
- •2. Инкапсуляция. Полиморфизм. Виртуальные функции. Чисто абстрактные базовые классы. Множественное наследование. Инкапсуляция.
- •Полиморфизм и виртуальные функции
- •Чисто абстрактные базовые классы
- •Множественное наследование классов. Компоненты
- •Типы операций:
- •Билет №26
- •1. Стратегия планирования «Зануление дуг» (Edge Zeroing - ez). Стратегия планирования «Зануление дуг» (Edge Zeroing - ez)
- •2. Преимущество использования компонентов. Требования к компонентам. Преимущества использования компонентов
- •Требования к компонентам
- •Билет №27
- •2. Модель компонентных объектов com.
- •Билет №28
- •1. Стратегия планирования «Управление мобильностью» (Mobility Directed - md). Стратегия планирования «Управление мобильностью» (Mobility Directed - md)
- •2. Интерфейс передачи сообщений (Message Passing Interface - mpi). Интерфейс передачи сообщений mpi
- •Билет №29
- •1. Граф взаимодействия задач. Граф разнородной сети. Планирование решения задач в разнородной распределенной системе
- •Постановка проблемы
- •2 . Интерфейс OpenMp. Интерфейс OpenMp
- •Билет №30
- •Постановка проблемы
- •Алгоритм а* оптимального назначения задач на процессоры
- •2. Технологический стандарт написания распределённых приложений corba. Технологический стандарт corba
2. Интерфейс передачи сообщений (Message Passing Interface - mpi). Интерфейс передачи сообщений mpi
Международным стандартом параллельного программирования является модель передачи сообщений MPI (Message Passing Interface). Рекомендуемой бесплатной реализацией MPI является пакет MPICH, разработанный в Арагонской национальной лаборатории.
MPI поддерживает несколько режимов передачи данных. Синхронная передача, не требует выделения промежуточных буферов для данных и обеспечивает надежную передачу данных сколь угодно большого размера. Асинхронная передача, при которой посылающий сообщение процесс не ждет начала приема, позволяет эффективно передавать короткие сообщения.
MPI позволяет передавать данные не только от одного процесса к другому, но и поддерживает коллективные операции: широковещательную передачу, разборку-сборку, операции редукции. Вычислительная система может включать разные процессоры, в том числе имеющие различные наборы команд и разное представление данных.
MPI поддерживает создание приложений в модели SPMD (single program multiple data) - одна программа работает в разных процессах со своими данными. Одна и та же функция вызывается на узле-источнике и узлах-приемниках, а тип выполняемой операции (передача или прием) определяется с помощью параметра. Такой вызов делает SPMD-программы существенно компактнее, хотя и труднее для понимания.
MPI - это стандарт на программный инструментарий для обеспечения связи между ветвями параллельного приложения. MPI предоставляет программисту единый механизм взаимодействия ветвей внутри параллельного приложения независимо от машинной архитектуры (однопроцессорные/многопроцессорные с общей/разделяемой памятью), взаимного расположения ветвей (на одном процессоре / на разных процессорах) и API операционной системы ( API = "applications programmers interface" = "интерфейс разработчика приложений" ).
Программа, использующая MPI, легче отлаживается (сужается простор для совершения стереотипных ошибок параллельного программирования) и быстрее переносится на другие платформы (в идеале, простой перекомпиляцией).
Создание параллельной программы включает в себя две основных стадии:
последовательный алгоритм подвергается декомпозиции (распараллеливанию), т.е. разбивается на независимо работающие ветви; для взаимодействия в ветви вводятся две дополнительные нематематические операции - прием и передача данных
распараллеленный алгоритм записывается в виде программы, в которой операции приема и передачи записываются в терминах конкретной системы связи между ветвями.
В настоящее время разными коллективами разработчиков написано несколько программных пакетов, удовлетворяющих спецификации MPI, в частности: MPICH, LAM, HPVM и так далее. Они выступают базовыми при переносе MPI на новые архитектуры ЭВМ.
Коммуникатор. Основное отличие стандарта MPI от его предшественников - понятие коммуникатора. Все операции синхронизации и передачи сообщений локализуются внутри коммуникатора. С коммуникатором связывается группа процессов. В частности, все коллективные операции вызываются одновременно на всех процессах, входящих в эту группу.
П
рактический
опыт показывает, что идеально
распараллеливаемые задачи, такие как
параллельное умножение матриц, можно
решать практически на любых сетях, и
добавление даже относительно слабых
вычислительных узлов дает выигрыш.
Другие задачи, в частности решение
систем линейных уравнений, более
требовательны к коммуникационному
оборудованию и качеству реализации
передачи сообщений. Именно поэтому
тесты для оценки реального быстродействия
параллельных вычислительных систем
базируются на параллельных аналогах
известного пакета Linpack. Так, система
линейных уравнений размером 800х800
решается на четырех компьютерах Sun
SPARCstation 5, объединенных сетью Ethernet 10
Мбит/c, быстрее, чем на трех; на пяти -
приблизительно за то же время, что и на
четырех, а добавление шестого компьютера
однозначно ухудшает производительность
вычислительной системы. Если вместо
Fast Ethernet 10 Мбит/c использовать Fast Ethernet
100 Мбит/с, что лишь незначительно
увеличивает общую стоимость системы,
время, затрачиваемое на коммуникацию,
уменьшается почти в 10 раз, а для решения
данной задачи можно будет эффективно
применять уже десятки рабочих станций.
Система связи, в свою очередь, включает в себя два компонента: программный и аппаратный. С точки зрения программиста базовых парадигм связи две - данные могут передаваться:
через разделяемую память, синхронизация доступа ветвей к такой памяти происходит посредством семафоров (разделяемая память и семафоры - SMP-машины);
в виде сообщений (индивидуальные интерфейсы с передачей сообщений - MPP-машины).
Общая организация MPI. MPI-программа представляет собой набор независимых процессов, каждый из которых выполняет свою собственную программу (не обязательно одну и ту же). Процессы взаимодействуют друг с другом посредством вызова коммуникационных процедур.
Каждый процесс выполняется в своем собственном адресном пространстве, однако допускается и режим разделения памяти. MPI не специфицирует модель выполнения процесса – это может быть как последовательный процесс, так и многопоточный.
MPI не предоставляет средств для распределения процессов по вычислительным узлам и для запуска их на исполнение. Эти функции возлагаются либо на операционную систему, либо на программиста. MPI не накладывает каких-либо ограничений на то, как процессы будут распределены по процессорам, в частности, возможен запуск MPI-программы с несколькими процессами на однопроцессорной системе.
Для идентификации наборов процессов вводится понятие группы, объединяющей все или какую-то часть процессов. Каждая группа образует область связи, с которой связывается специальный объект – коммуникатор области связи MPI_COMM_WORLD. Процессы внутри группы нумеруются целым числом в диапазоне 0...groupsize-1. Все коммуникационные операции с некоторым коммуникатором будут выполняться только внутри области связи, описываемой этим коммуникатором.
Библиотека. MPI является библиотекой функций межпроцессного обмена сообщениями и содержит около 130 функций, которые делятся на следующие классы: операции точка-точка, операции коллективного обмена, топологические операции, системные и вспомогательные операции.
В принципе, любая параллельная программа может быть написана с использованием всего 6 MPI-функций, а достаточно полную и удобную среду программирования составляет набор из 24 функций. Определение всех именованных констант, прототипов функций и определение типов выполняется подключением файла mpi.h.
Любая прикладная MPI-программа (приложение) должна начинаться с вызова функции инициализации MPI – функции MPI_Init. В результате выполнения этой функции создаются все процессы приложения, и создается область связи, описываемая предопределенным коммуникатором MPI_COMM_WORLD. Процессы в группе упорядочены и пронумерованы от 0 до groupsize-1. Кроме этого создается предопределенный коммуникатор MPI_COMM_SELF, описывающий свою область связи для каждого отдельного процесса.
Прототип функции инициализации:
int MPI_Init(int *argc, char ***argv);
В программах на C каждому процессу при инициализации передаются аргументы функции main, полученные из командной строки. В программах на языке FORTRAN параметр IERROR является выходным и возвращает код ошибки.
Функция завершения MPI-программ MPI_Finalize:
int MPI_Finalize(void);
Она закрывает все MPI-процессы и ликвидирует все области связи.
Функция определения числа процессов в области связи MPI_Comm_size:
int MPI_Comm_size(MPI_Comm comm, int *size);
comm – коммуникатор;
size – число процессов в области связи коммуникатора comm.
Функция возвращает количество процессов в области связи коммуникатора comm.
До создания явным образом групп и связанных с ними коммуникаторов единственно возможными значениями параметра COMM являются MPI_COMM_WORLD и MPI_COMM_SELF, которые создаются автоматически при инициализации MPI.
Функция определения номера процесса MPI_Comm_rank:
int MPI_Comm_rank(MPI_Comm comm, int *rank)
comm – коммуникатор;
rank – номер процесса, вызвавшего функцию.
Функция возвращает номер процесса, вызвавшего эту функцию. Номера процессов лежат в диапазоне 0..size-1 (значение size может быть определено с помощью предыдущей функции). Подпрограмма является локальной.
В минимальный набор входят две функции передачи и приема сообщений.
Функция передачи сообщения MPI_Send:
int MPI_Send(void* buf, int count, MPI_Datatype datatype,
int dest, int tag, MPI_Comm comm);
buf – адрес начала расположения пересылаемых данных;
count – число пересылаемых элементов;
datatype – тип посылаемых элементов;
d
est
– номер процесса-получателя в группе,
связанной с коммуникатором comm;
tag – идентификатор сообщения (аналог типа сообщения функций nread и nwrite PSE nCUBE2);
comm – коммуникатор области связи.
Функция выполняет посылку count элементов типа datatype сообщения с идентификатором tag процессу dest в области связи коммуникатора comm. Переменная buf – это, как правило, массив или скалярная переменная. В последнем случае значение count = 1.
Функция приема сообщения MPI_Recv:
int MPI_Recv(void* buf, int count, MPI_Datatype datatype,
int source, int tag, MPI_Comm comm, MPI_Status *status)
buf – адрес начала расположения принимаемого сообщения;
count – максимальное число принимаемых элементов;
datatype – тип элементов принимаемого сообщения;
source – номер процесса-отправителя;
tag – идентификатор сообщения;
comm – коммуникатор области связи;
status – атрибуты принятого сообщения.
Функция выполняет прием count элементов типа datatype сообщения с идентификатором tag от процесса source в области связи коммуникатора comm.
Приведем с использованием MPI пример программы вычисления числа π. Вычисление числа π сводится к вычислению интеграла по следующей формуле:
где .
Программа на языке С:
#include "mpi.h"
#include <math.h>
int main ( int argc, char *argv[] ) {
int n, myid, numprocs, i; /* число ординат, имя и число процессов*/
double PI25DT = 3.141592653589793238462643; /* для оценки точности вычислений */
double mypi, pi, h, sum, x;
/* mypi – частное значение отдельного процесса, pi – полное значение . */
MPI_Init(&argc, &argv); /* задаются системой*/
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
while (1) {
if (myid == 0) {
printf ("Enter the number of intervals: (0 quits) "); /*ввод числа ординат*/
scanf ("%d", &n);
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (n == 0) /* задание условия выхода из программы */
break;
else {
h = 1.0/ (double) n; /* вычисление частного значения . некоторого процесса */
sum = 0.0;
for (i = myid +1; i <= n; i+= numprocs) {
x = h * ( (double)i - 0.5);
sum += (4.0 / (1.0 + x*x));
}
mypi = h * sum; /* вычисление частного значения . некоторого процесса */
MPI_Reduce(&mypi,&pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
/* сборка полного значения . */
if (myid == 0) /* оценка погрешности вычислений */
printf ("pi is approximately %.16f. Error is %.16f\n", pi, fabs(pi - PI25DT));
}
}
MPI_Finalize(); /* выход из MPI */
return 0;
}
Задача - Привести пример кода создания компонента.
int main()
{
printf(rus("\nИнициализация COM ..."));
if ( FAILED( CoInitialize( NULL )))
{
printf(rus("\nОшибка при инициализации COM ..."));
printf(rus("\n\nНажмите любую клавишу для продолжения..."));
getchar();
return -1;
}
printf(rus("\nПолучение интерфейса фабрики классов для класса Plan..."));
hr = CoGetClassObject(CLSID_Plan,CLSCTX_LOCAL_SERVER,NULL,IID_IClassFactory,(void**)&pICF);
if ( FAILED( hr ))
{
printf(rus("\nОшибка при получении указателя на интерфейс фабрики классов. Код ошиибки %X"),hr);
printf(rus("\n\nНажмите любую клавишу для продолжения..."));
getchar();
return -1;
};
IUnknown* pIUnk;
hr = pICF->CreateInstance( NULL, IID_IUnknown, (void**) &pIUnk );
pICF->Release();
if ( FAILED( hr ))
{
printf(rus("\nОшибка при создании экземпляра компонента. Код ошибки %X"),hr);
printf(rus("\n\nНажмите любую клавишу для продолжения..."));
getchar();
return -1;
};
printf(rus("\nЭкземпляр компонента успешно создан "));
printf(rus("\n\nНажмите любую клавишу для продолжения..."));
getchar();
hr = pIUnk->QueryInterface( IID_IPlan, (LPVOID*)&pPlan );
pIUnk->Release();
if ( FAILED( hr ))
{
printf(rus("Ошибка при запросе интерфейса IPlan. Код ошибки %X"),hr);
printf(rus("\n\nНажмите любую клавишу для продолжения..."));
getchar();
getchar();
return -1;
}
DWORD c = 0;
pPlan->Summ(3,4,&c);
printf(rus("Результат - %d"),c);
//char str[256];
//gets(str);
getchar();
return 0;
}
HRESULT __stdcall COMPFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid, void** ppv) {
if (pUnknownOuter != NULL) { // Агрегирование не поддерживается
return CLASS_E_NOAGGREGATION;
}
COMP* pCOMP = new COMP;
if (pCOMP == NULL) {
return E_OUTOFMEMORY;
}
HRESULT hr = pCOMP->QueryInterface(iid, ppv);
// (Если QueryInterface отработает неудачно, компонент удалит сам себя)
pCOMP->Release();
return hr;
}