Министерство образования Российской Федерации
Санкт-Петербургский государственный
архитектурно-строительный университет
Кафедра прикладной математики и информатики
Дипломная работа
АЛГОРИТМЫ ПАРАЛЛЕЛЬНЫХ ПРОЦЕССОВ ПРИ ИССЛЕДОВАНИИ УСТОЙЧИВОСТИПОДКРЕПЛЕННЫХ ПОЛОГИХ ОБОЛОЧЕК
Выполнил студент
группы ПМ-V
Сизов А.С.
Дипломный руководитель
доктор технических наук
проф. Карпов В.В.
Санкт-Петербург 2010
Оглавление
Введение
Глава 1. Математические модели деформирования подкрепленныхпологих оболочек при учете различных свойствматериала
Глава 2. Традиционные алгоритмы решения задач устойчивостидля подкрепленных пологих оболочек
2.1 Программа PologObolochka
Глава 3. Распараллеливание процесса вычисления. Основы,принципы, практическое применение
3.1 Message Passing Interface
3.2 MPICH
3.3 Принципы работы MPICH
3.4 Установка MPICH в Windows
3.5 Настройка MPICH
3.6 Создание общего сетевого ресурса
3.7 Запуск MPI-программ
Глава 4. Алгоритмы решения задач устойчивости дляподкрепленных пологих оболочек, основанные на распараллеливании процессавычисления
4.1 Программа и результаты
Заключение
Литература
Приложения
Введение
Работа выполнена в соответствиис грантом Минобнауки РФ «Развитие научного потенциала высшей школы (2009-2010г. г)», тема №2.1 2/6146. Разрабатывается программный комплекс расчетовпрочности и устойчивости подкрепленных оболочек вращения с учетом различныхсвойств материала. Используются наиболее точные модели деформирования оболочек.Усложнение расчетных уравнений приводит к существенному увеличению временирасчета одного варианта задачи на ЭВМ при последовательных вычислениях. Чемтоньше оболочка, тем больше изменяемость формы поверхности оболочки придеформировании. Это приводит к увеличению числа членов разложения искомых функцийв ряды в методе Ритца, чтобы точность расчетов была высока. Так, при удержании9 членов в разложении искомых функций (N = 9) время расчета одного варианта, взависимости от кривизны оболочки и числа подкрепляющих ее ребер, составляет 1-3часа, при N = 64 — несколько суток. Для существенного сокращения временирасчета одного варианта задачи на ЭВМ требуется оптимизация программы. Один изпутей решения данной проблемы состоит в распараллеливании процессов вычисления.
Расширение возможностей вконструировании вычислительной техники всегда оказывало влияние на развитиевычислительной математики — в первую очередь численных методов и численногопрограммного обеспечения. В условиях появления больших параллельных систем исоздания сверхмощных новых систем перед математиками, и в особенностиматематиками-прикладниками, открывается обширнейшая область исследований,связанная с совместным изучением параллельных структур численных методов ивычислительных систем. [5]
Глава 1. Математические модели деформированияподкрепленных пологих оболочек при учете различных свойств материала
Оболочки покрытия и перекрытиястроительных сооружений не могут допускать прогибы, соизмеримые с их толщиной,поэтому можно вести их расчет в геометрически линейной постановке, при этомсущественно упрощаются все соотношения. В этом случае функционал полной энергиидеформации ребристой оболочки при действии на нее поперечной нагрузки /> будет иметь вид
/> (1)
где />,если учитывается физическая нелинейность, />,если учитывается ползучесть материала.
Для металлов ползучесть можетразвиваться только при больших температурах, поэтому будем считать />. Для оргстекла зависимость "/>" практически линейная, поэтому можнопринять />.
Здесь
/>
/>
/>
/> (2)
/>
/>
/> (3)
/>
/>
/>
/>
/> (4)
или, если принимаетсяитерационный процесс по временной координате,
/>
/>
/>
/>
/> (5)
где />
/> (6)
Срединная поверхность пологойоболочки прямоугольного плана постоянной толщины образована перемещениемпологой дуги окружности радиуса /> вдоль пологойдуги окружности радиуса />.
Поверхность такого вида называютповерхностью переноса. Оболочка называется пологой, если отношение стрелыподъема /> оболочки к наименьшему линейномуразмеру /> удовлетворяет соотношению /> (рис.1). Так как стрела подъема пологойоболочки мала />, то геометрия пологойоболочки близка к геометрии пластины, поэтому параметры Ляме приближеннопринимаются равными единице: />
/>
Рис.1. Пологая оболочка двоякойкривизны
Для пологих оболочек считается,что при деформации образуются сравнительно мелкие вмятины, размеры которых малыпо сравнению с радиусами кривизны оболочки, и также считается, что функцияпрогиба является быстро изменяющейся функцией, т.е. отношение W к еепервой производной является малой величиной.
Геометрические соотношения дляпологих оболочек при учете поперечных сдвигов принимают вид
/>
/> (7)
/>
Кроме того, /> имеют вид (2.7),
/>
/>
Функции изменения кривизн /> и кручения /> принимаютвид
/> /> (8)
Выражения для /> здесь принимают вид
/> /> (9)
Глава 2. Традиционные алгоритмы решения задач устойчивостидля подкрепленных пологих оболочек
После применения метода Ритца кфункционалу (1) при аппроксимации функций перемещений в виде
/>,/>,
/>,(10)
получим системуинтегро-алгебраических уравнений
/> (11)
для определения неизвестныхчисловых параметров />, />,/>.
Следует обратить внимание на то,что для конических, сферических и торообразных оболочек аппроксимирующиефункции по переменной /> должны иметь исимметричные, и несимметричные составляющие (если это синусы, то должны быть /> и т.д.).
Систему (11) распишем подробно,отдельно вычислив
/>
В начале вычислим />, учитывая, что для оболочек вращения />, (сомножитель /> опускаем)
/>
/>
/>
/>
/> (12)
/>
/>
/> (13)
/>
/>
/>
/>
/>
/> (14)
Для решения системы уравненийпредполагается использовать метод упругих решений А.А. Ильюшина [9], т.е. методитераций, когда на каждой итерации решается линейно-упругая задача сизменяющейся правой частью (/>)
/>
/> (15)
/>
где /> равны/> или />.Здесь
/>,/>, />,
/>,/>, />.
В выражениях, стоящих в левойчасти системы (15), пренебрегается сомножителем />,поэтому его не будет и в /> и />.
Так как /> и/> будут вычислены при известных />, />, />, то расписывать эти выражения через />, />, /> нет смысла. Правые части системы (15) играютроль фиктивной нагрузки.
При вычислении /> примем
/>,(16)
где
/>.
Для металла, не имеющегоплощадки текучести, /> принимает значение от /> до />ивычисляется эмпирически, для железобетона
/>.
Аппроксимация (16) справедливапри малой нелинейности.
Выражение для /> представим в виде
/>,
где
/> (17)
Так как
/>,
то
/>
/> (18)
/>
где
/> />, />,
/>,/>.
Теперь вычислим /> (опуская сомножитель
/>)
/>
/>
/>
/> (19)
/>
/> (20)
/>
/>
/>
/>
/> (21)
Систему (15) кратко можнозаписать в виде
/> (22)
где /> равняется/> или
/>;/>
/> -левые части системы (15);
/> />
/>
При решении физически-нелинейнойзадачи для каждого значения параметра нагрузки решается итерационная задача
/> (23),до тех пор, пока
/>.
Начальное приближение /> находится из решения линейно-упругой задачи
/> (24)
Метод упругих решений — самыйпростой и распространенный метод решения нелинейно упругих задач. В работе [15]к уравнениям равновесия применялся метод последовательных нагружений приисследовании напряженно-деформированного состояния плиты в условиях нелинейногодеформирования, но для ребристых оболочек такая методика приводит к громоздкимуравнениям.
При вычислении /> опускаем сомножитель />.В результате получим два варианта соотношений. Первый вариант получается, если /> взять в виде (4) и тогда
/>
/> (25)
/>
/> (26)
/>
/> (27)
Решение задач ползучести дляоболочек возможно лишь при применении приближенных методик.
Чтобы избежать решенияинтегральных уравнений, интегралы по переменной /> наотрезке /> разобьем на сумму интегралов почастичным отрезкам />, обозначив />, и последние вычислим приближенно по формулепрямоугольников. Такая методика применялась в работах [14, 8].
В результате /> примут вид
/>
/>
/>
/>
/> (28)
/>
/> (29)
/>
/>
/>
/>
/> (30)
Здесь /> имеютвид (6). Например, для оргстекла [14]
/> (31),где
/>
/> итогда
/> (32)
для старого бетона [2]
/> (33),где
/> итогда
/> (34)
При решении задач ползучести дляоболочек при каждом значении параметра нагрузки /> решаетсяитерационная задача
/> (35)
до тех пор, пока прогибы небудут резко возрастать (в 10-15 раз по сравнению с первоначальным значением).
Начальное приближение /> находится из решения линейно-упругой задачи(24).
Второй вариант соотношений /> получается, если взять /> в виде (5) и тогда (так как деформации при /> считаются известными, то производные от нихпо /> равны нулю)
/>
/>
/>
/> (36)
/>
/>
/> (37)
/>
/>
/>
/>
/>
/> (38)
Таким образом, выражения /> оказываются одинаковыми, как для />, взятого в виде (4), так и для />, взятого в виде (5). При учетегеометрической нелинейности такого полного совпадения не будет. Прииспользовании /> в виде (5) значение правых частейсистемы (15) будут несколько больше, чем при использовании /> в виде (4), что пойдет в запас прочности.
2.1 ПрограммаPologObolochka
Программа предназначена длярасчетов прочности и устойчивости оболочек при учете геометрической ифизической нелинейностей и ползучести материала и разработана Беркалиевым Р.Т.[11] Программа может быть запущенна под любой версией ОС Windows, начиная сверсии NT.
Программа состоит из несколькихбазовых блоков:
Получение коэффициентов С системалгебраических уравнений линейно-упругой задачи;
Метод итераций для геометрическии физически-нелинейной задачи;
Построения графиков устойчивости;
Построение 3-D графиковустойчивости;
Метод итераций ползучести (спостроением графиков);
Построение 3-D графиковползучести.
От физической модели не зависитблок 1, все остальные блоки зависят от нее. Таким образом, в зависимости отфизической линейности или нелинейности вызываются соответствующие блоки. Блок 1и блок 2 являются базовыми для расчета любой задачи.
Блок 1: Получениекоэффициентов С систем алгебраических уравнений линейно-упругой задачи.
Блок вычисляет коэффициенты Cдля составления базовой системы уравнений модели расчета, и записывает их вфайл, чтобы в дальнейшем, для этой же задачи загрузить их из файла. Коэффициентывычисляются по ряду параметров, которые запрещено менять в дальнейших вычислениях,при расчете текущей задачи.
Блок 2: Метод итераций длягеометрически и физически-нелинейной задачи.
Метод итераций проводит расчетустойчивости как физически линейных, так и физически нелинейных моделейоболочек, в зависимости от выбранной модели.
В процессе метода итераций, позаданному фильтру PausePW, сохраняются значения P, U, V, W,PS, PN в файл, и сохраняется последнее состояние метода. Вдальнейшем оттуда берутся данные для продолжения метода итераций, в случае егоаварийного завершения. Таким образом, метод итераций может быть прерван в любоймомент времени и потом продолжен с момента его прерывания.
Блок 3: Построения графиковустойчивости.
По заданному фильтрусоставляется зависимость P-W. Из файла метода Итераций берутся этизначения, и вычисляются прогибы, для P-W, и заносятся в файл. Блоксоставляет файл зависимости P-W, по которому может быть построен графикзависимости.
Блок 4: Построение 3-Dграфиков устойчивости.
По заданному фильтрусоставляются поля прогибов и напряжений для оболочки для физически линейной илинелинейной модели. Вычисления ведутся только для тех значений, нагрузка-P,которые попадают в список заданных нагрузок, для которых запрашивались прогибыи напряжения.
Из файла блока метода итерацийсчитывается U, V, W, PS, PN, для заданных P,и вычисляют поля прогибов W (x,y) и напряжений /> (x,y) и они записываются вфайлы. По сохраненным расчетам могут быть построены графики. Интенсивностьнапряжений /> (x,y) вычисляется взависимости от материала (хрупкие или пластичные).
Блок 5: Метод итерацийползучести.
По заданному фильтру блокпроизводит расчет ползучести оболочки для физически линейной или нелинейноймодели. Из файла метода итераций считываются U, V, W, PS,PN, для заданных P. Для каждого P инициализируется системауравнений ползучести, и ведется расчет ползучести материала, и составляетсязависимость W-t, которая записывается в файл. Эта зависимость может бытьв дальнейшем представлена в графическом виде.
Блок 6: Построение 3-Dграфиков ползучести.
По заданному фильтрупроизводится расчет полей прогибов и напряжений для физически линейной илинелинейной задачи. Из файла метода итераций считываются U, V, W,PS, PN, для выбранного P. Инициализируется системауравнений, и ведется расчет. Для заданных точек по времени составляются поляпрогибов и напряжений, в зависимости от материала и физической модели оболочки,которые записываются в файлы. По результатам расчета могут быть построеныграфические зависимости.
Для графического представлениязависимостей используется математический пакет Maple, начиная с версии Maple 6.
Для расчета любой задачивходными данными являются выбор физической модели: физически линейная илифизически нелинейная (рис.2).
/>
Рис.2. Выбор модели
Входными данными являются:
Dim_a — Линейный размер оболочки;
Kksi — Кривизна оболочки вдольнаправления X;
Keta — Кривизна оболочки вдольнаправления Y;
lambda — Соотношение длин сторонвдоль направления X и Y оболочки;
Mu — Коэффициент Пуассона;
J_m — Количество ребер жесткостивдоль направления X;
I_n — Количество ребер жесткостивдоль направления Y;
AutomaticModeRebra — Режим вводацентральных координат ребер жесткости;
F_j — Высота ребер жесткостивдоль направления X;
F_i — Высота ребер жесткостивдоль направления Y;
rj — Ширина ребер жесткостивдоль направления X;
ri — Ширина ребер жесткостивдоль направления Y;
temporaryRebraX — Центральныекоординаты ребер жесткости вдоль направления X;
temporaryRebraY — Центральныекоординаты ребер жесткости вдоль направления Y;
N — Количество аппроксимирующихфункций;
N_Simps — Разбиение привычислении интегралов для коэффициентов СЛАУ;
P_KON — Конечная нагрузка;
d_P — Шаг по нагрузке методаИтераций;
PausePW — Шаг по нагрузке выводарезультатов расчета;
epsilon — Точность методаИтераций;
Iter_X1 — Координата Xвычисления прогиба оболочки для метода Итераций;
Iter_Y1 — Координата Yвычисления прогиба оболочки для метода Итераций;
Ust_X1 — Координата Xвычисления прогиба оболочки для построения 1-й зависимости P-W;
Ust_Y1 — Координата Yвычисления прогиба оболочки для построения 1-й зависимости P-W;
Ust_X2 — Координата Xвычисления прогиба оболочки для построения 2-й зависимости P-W;
Ust_Y2 — Координата Yвычисления прогиба оболочки для построения 2-й зависимости P-W;
Ust_P — Значения нагрузок длявывода полей прогиба и интенсивности оболочки;
CreepEnd — Порог превышенияпрогиба для вычисления ползучести оболочки;
Creep_X1 — Координата Xвычисления прогиба оболочки для построения 1-й зависимости W-t;
Creep_Y1 — Координата Yвычисления прогиба оболочки для построения 1-й зависимости W-t;
Creep_X2 — Координата Xвычисления прогиба оболочки для построения 2-й зависимости W-t;
Creep_Y2 — Координата Yвычисления прогиба оболочки для построения 2-й зависимости W-t;
Creep_P — Значения нагрузок длявычисления ползучести оболочки;
DimP_Time — Значение нагрузкидля вывода динамических полей прогиба и интенсивности оболочки;
CreepTime — Значения времени длявывода динамических полей прогиба и интенсивности оболочки при заданнойнагрузке;
Material — Тип материала (дляупругих материалов задача ползучести не рассчитывается);
constM — Константа физическойнелинейности.
При вводе данных программапоказывает подсказку по каждому параметру (рис.3).
После ввода всех параметровможно приступать к расчету.
/>
Рис.3. Ввод входных данныхГлава 3. Распараллеливание процесса вычисления. Основы,принципы, практическое применение
Распараллеливание процессавычисления — процесс адаптации алгоритмов, записанных в виде программ,для их эффективного исполнения на вычислительной системе параллельной архитектуры.Заключается либо в переписывании программ на специальный язык, описывающийпараллелизм и понятный трансляторам целевой вычислительной системы, либо квставке специальной разметки (например, инструкций MPI или OpenMP[1]). [1]
История
В 1973 году Джон Шох и Джон Хаппиз калифорнийского научно-исследовательского центра Xerox PARCнаписали программу, которая по ночам запускалась в локальную сеть PARC изаставляла работающие компьютеры выполнять вычисления.
В 1988 году Арьен Ленстра и Марк Менес написалипрограмму для факторизации длинных чисел. Для ускоренияпроцесса программа могла запускаться на нескольких машинах, каждая из которыхобрабатывала свой небольшой фрагмент. Новые блоки заданий рассылались накомпьютеры участников с центрального сервера проекта по электронной почте. Для успешногоразложения на множители числа длиной в сто знаков этому сообществупотребовалось два года и несколько сотен персональных компьютеров.
С появлением и бурным развитием интернета всё большую популярность сталаполучать идея добровольного использования для распределённых вычисленийкомпьютеров простых пользователей, соединённых через интернет.
В январе 1996 года стартовалпроект GIMPSпо поиску простых чисел Мерсенна.
28 января 1997 года стартовалконкурс RSA Data Security на решение задачи взлома методом простого перебора56-битного ключа шифрования информации RC5. Благодаряхорошей технической и организационной подготовке проект, организованныйнекоммерческим сообществом distributed.net,быстро получил широкую известность.
17 мая 1999 года на базеплатформы BOINCзапущен проект SETI@home, занимающийся поискомвнеземного разума путем анализа данных с радиотелескопов (анализ данных проводилсяи раньше, но без использования грид).
Такие проекты распределённыхвычислений в интернете, как SETI@Homeи Folding@Homeобладает не меньшей вычислительной мощностью, чем самые современные суперкомпьютеры. Интегральный объемвычислений на платформе BOINC поданным на 16 мая 2010 года составляет 5.2 петафлопс, в товремя как пиковая производительность самого мощного суперкомпьютера (Jaguar — Cray XT5-HE)- «всего» 2.3 петафлопс. Проект отмечен в Книге рекордов Гиннеса как самое большоевычисление.
Распараллеливание может бытьручным, автоматизированным и полуавтоматизированным. Для оценки эффективностиего качества применяются следующие критерии:
Ускорение />, где /> -время исполнения распараллеленной программы на p процессорах, /> - время исполнения исходной программы. Видеальном случае (отсутствие накладных расходов на организацию параллелизма) равна/>.
Загруженность />, показывающая долю использования процессоров.В идеальном случае равна 1, или 100%. Эта величина зачастую гораздо болеенаглядно характеризует эффективность параллелизма в серии испытаний при разных />, чем />,особенно на графиках.
При распараллеливании важноучитывать не только формальный параллелизм структуры алгоритма, но и то, чтообменные операции в параллельных ЭВМпроисходят, как правило, значительно медленнее арифметических. С этим связаносуществование львиной доли накладных расходов на организацию параллелизма.
В информатике параллельный алгоритм,противопоставляемый традиционным последовательным алгоритмам, — алгоритм, который может быть реализованпо частям на множестве различных вычислительных устройств с последующимобъединением полученных результатов и получением корректного результата.
Некоторые алгоритмы достаточнопросто поддаются разбиению на независимо выполняемые фрагменты. Например,распределение работы по проверке всех чисел от 1 до 100000 на предмет того,какие из них являются простыми, может быть выполнено путемназначения каждому доступному процессору некоторого подмножества чисел споследующим объединением полученных множеств простых чисел (похожим образомреализован, например, проект GIMPS[2]).
С другой стороны, большинствоизвестных алгоритмов вычисления значения числа π не допускают разбиения напараллельно выполняемые части, т.к требуют результата предыдущей итерациивыполнения алгоритма. Итеративные численные методы, такие как,например, метод Ньютона или задача трёх тел, также являются сугубопоследовательными алгоритмами. Некоторые примеры рекурсивных алгоритмов достаточно сложноподдаются распараллеливанию.
Параллельные алгоритмы весьмаважны ввиду постоянного совершенствования многопроцессорныхсистем и увеличения числа ядер в современных процессорах. Обычнопроще сконструировать компьютер с одним быстрым процессором, чем с множествоммедленных процессоров (при условии достижения одинаковой производительности).Однако производительность процессоров увеличивается главным образом за счетсовершенствования техпроцесса (уменьшения норм производства), чему мешают физические ограничения на размерэлементов микросхем и тепловыделение. Указанные ограничения могут быть преодоленыпутем перехода к многопроцессорной обработке, что оказывается эффективным дажедля малых вычислительных систем.
Сложность последовательныхалгоритмов выражается в объеме используемой памяти и времени (числе тактовпроцессора), необходимых для выполнения алгоритма. Параллельные алгоритмытребуют учета использования еще одного ресурса: подсистемы связей междуразличными процессорами. Существует два способа обмена между процессорами: использованиеобщей памяти и системы передачи сообщений.
Системы собщей памятью требуют введения дополнительных блокировок для обрабатываемыхданных, налагая определенные ограничения при использовании дополнительныхпроцессоров.
Системы передачи сообщенийиспользуют понятия каналов и блоков сообщений, что создает дополнительныйтрафик на шине и требует дополнительных затрат памяти для организации очередейсообщений. В дизайне современных процессоров могут быть предусмотрены специальныекоммутаторы (кроссбары) с целью уменьшения влияния обмена сообщениями на времявыполнения задачи.
Еще одной проблемой, связанной сиспользованием параллельных алгоритмов, является балансировка нагрузки. Например, поискпростых чисел в диапазоне от 1 до 100000 легко распределить между имеющимисяпроцессорами, однако некоторые процессоры могут получить больший объем работы,в то время как другие закончат обработку раньше и будут простаивать. Проблемыбалансировки нагрузки еще больше усугубляется при использовании гетерогенныхвычислительных сред, в которых вычислительные элементы существенно отличаютсяпо производительности и доступности (например, в грид-системах).
Разновидность параллельныхалгоритмов, называемая распределенными алгоритмами,специально разрабатываются для применения на кластерах и в распределенных вычислительных системахс учетом ряда особенностей подобной обработки.
В данной работе был выбранинтерфейс MPI для распараллеливания процесса, так как он наиболее удобен длясоздаваемого программного пакета. Ведь заранее неизвестно, какие вычислительныемашины и какой конфигурации будут использоваться. MPI позволяет эмулировать[3]вычислительные машины на ядрах одного процессора, что, в некоторых случаях,гораздо более эффективнее при вычислениях.
3.1 MessagePassing Interface
Message Passing Interface (MPI,интерфейс передачи сообщений) — программный интерфейс (API) дляпередачи информации, который позволяетобмениваться сообщениями между процессами, выполняющими одну задачу. РазработанУильямомГроуппом, Эвином Ласком и другими.
MPI является наиболеераспространённым стандартом интерфейса обмена данными в параллельном программировании,существуют его реализации для большого числа компьютерных платформ. Используетсяпри разработке программ для кластеров и суперкомпьютеров. Основным средствомкоммуникации между процессами в MPI является передачасообщений друг другу. Стандартизацией MPI занимается MPI Forum. В стандарте MPIописан интерфейс передачи сообщений, который должен поддерживаться как наплатформе, так и в приложениях пользователя. Внастоящее время существует большое количество бесплатных и коммерческихреализаций MPI. Существуют реализации для языков Фортран 77/90, Си и Си++.
Стандарты MPI
Большинство современныхреализаций MPI поддерживают версию 1.1 Стандарт MPI версии 2.0 поддерживаетсябольшинством современных реализаций, однако некоторые функции могут бытьреализованы не до конца.
В MPI 1.1 (опубликован 12 июня1995 года)поддерживаются следующие функции:
передача и получение сообщениймежду отдельными процессами;
коллективные взаимодействияпроцессов;
взаимодействия в группахпроцессов;
реализация топологий процессов;
В MPI 2.0 (опубликован 18 июля1997 года)дополнительно поддерживаются следующие функции:
динамическое порождениепроцессов и управление процессами;
односторонние коммуникации (Get/Put);
параллельный ввод и вывод;
расширенные коллективныеоперации (процессы могут выполнять коллективные операции не только внутриодного коммуникатора, но и в рамках нескольких коммуникаторов).
Пример программы
Ниже приведён пример программына C с использованием MPI:
// Подключение необходимых заголовков
#include
#include
#include «mpi. h»
// Функция дляпромежуточных вычислений
double f (doublea)
{
return (4.0/ (1.0+a*a));
}
// Главная функция программы
int main (int argc, char**argv)
{
// Объявление переменных
int done = 0, n,myid, numprocs, i;
double PI25DT = 3.141592653589793238462643;
double mypi, pi, h,sum, x;
double startwtime= 0.0, endwtime;
int namelen;
charprocessor_name [MPI_MAX_PROCESSOR_NAME] ;
// Инициализацияподсистемы MPI
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank (MPI_COMM_WORLD,&myid);
MPI_Get_processor_name (processor_name,&namelen);
// Выводномера потока в общем пуле
fprintf (stdout, «Process%d of%d is on%s\n»,myid,numprocs,processor_name);
fflush (stdout);
while(! done)
{
// количество интервалов
if (myid==0)
{
fprintf (stdout, «Enter the number of intervals: (0 quits)»);
fflush (stdout);
if (scanf ("%d",&n)!= 1)
{
fprintf (stdout, «No number entered; quitting\n»);
n = 0;
}
startwtime = MPI_Wtime ();
}
// Рассылка количества интервалов всем процессам (в томчисле и себе)
MPI_Bcast (&n, 1,MPI_INT, 0, MPI_COMM_WORLD);
if (n==0)
done = 1;
else
{
h = 1.0/ (double) n;
sum = 0.0;
// Обсчитывание точки, закрепленной за процессом
for (i = myid + 1;(i
{
x = h * ((double) i — 0.5);
sum += f (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));
endwtime = MPI_Wtime ();
printf («wall clock time =%f\n», endwtime-startwtime);
fflush (stdout);
}
}
}
// Освобождение подсистемы MPI
MPI_Finalize ();
return 0;
}
Реализации MPI
MPICH — самая распространённая бесплатная реализация, работает на UNIX-системахи Windows NT;
WMPI — бесплатная реализацияMPI для Windows;
LAM/MPI- ещё одна бесплатная реализация MPI;
MPI/PRO forWindows NT — коммерческая реализация для Windows NT;
Intel MPI- коммерческая реализация для Windows / GNU/Linux;
HP-MPI- коммерческая реализация от HP;
SGI MPT — платнаябиблиотека MPI от SGI;
Mvapich — бесплатнаяреализация MPI для Infiniband;
Open MPI — бесплатная реализация MPI,наследник LAM/MPI;
Oracle HPCClusterTools — бесплатная реализация для Solaris SPARC/x86 и Linux наоснове Open MPI.
3.2 MPICH
MPICH («MPI Chameleon»)- это одна из самых первых разработанных библиотек MPI. На еебазе было создано большое количество других библиотек как OpenSource,так и коммерческих.В настоящее время существует две ветви исходных кодов: MPICH1и MPICH2. Разработкаветви MPICH1 заморожена. Ветвь MPICH2 активно разрабатывается в Арагонскойлаборатории, с участием IBM, Cray, SiCortex, Microsoft, Intel, NetEffect,Qlogic, Myricom, Ohio state university, UBC.
MPICH2 — легко портируемаябыстрая реализация стандарта MPI. Отличительные особенности:
Поддерживает различныевычислительные и коммуникационные платформы, включая общедоступные кластеры (настольныесистемы, системы с общей памятью, многоядерные архитектуры), высокоскоростныесети (Ethernet 10 ГБит/с, InfiniBand, Myrinet,Quadrics) и эксклюзивные вычислительные системы (Blue Gene,Cray, SiCortex).
Модульная структура для созданияпроизводных реализаций, предоставляющая широкие возможности для исследованиятехнологии MPI.
В дальнейшем будем предполагать,что имеется сеть из нескольких компьютеров (будем называть их вычислительнымиузлами), работающих под управлением Windows. Для учебных целей можнозапускать все вычислительные процессы и на одном компьютере. Если компьютеродноядерный, то, естественно, прирост быстродействия не получится, — толькозамедление. В качестве среды разработки использовалась IDE Microsoft VisualStudio 2008 C++ Express Edition. Microsoft Visual Studio — линейка продуктовкомпании Майкрософт, включающих интегрированную среду разработкипрограммного обеспечения и ряд других инструментальных средств. MicrosoftVisual Studio 2008 C++ Express Edition — легковесная среда разработки,представляющая собой урезанную версию Visual Studio. В отличие от полнойверсии, такая среда предназначена для языка программирования C/C++. Онавключает в себя небольшой набор инструментов, в отличие от полных версий: отсутствуетдизайнер классов и многие другие инструменты, а также поддержка плагинов и удалённых баз данных в дизайнере данных. Компиляторыв 64-битный код также недоступны в Express редакциях. Microsoftпозиционирует эту линейку IDE для студентов. Программу,использующую MPI, и предназначенную для запуска на нескольких вычислительныхузлах, будем называть MPI-программой.
3.3 Принципы работы MPICH
MPICH для Windows состоит изследующих компонентов:
Менеджер процессов smpd. exe,который представляет собой системную службу (сервисное приложение). Менеджерпроцессов ведёт список вычислительных узлов системы, и запускает на этих узлахMPI-программы, предоставляя им необходимую информацию для работы и обменасообщениями;
Заголовочные файлы (. h) и библиотекистадии компиляции (. lib), необходимые для разработки MPI-программ;
Библиотеки времени выполнения (.dll), необходимые для работы MPI-программ;
Дополнительные утилиты (. exe),необходимые для настройки MPICH и запуска MPI-программ.
Все компоненты, кроме библиотеквремени выполнения, устанавливаются по умолчанию в папку C: \ProgramFiles\MPICH2; dll-библиотеки устанавливаются в C: \Windows\System32.
Менеджер процессов являетсяосновным компонентом, который должен быть установлен и настроен на всехкомпьютерах сети (библиотеки времени выполнения можно, в крайнем случае,копировать вместе с MPI-программой). Остальные файлы требуются для разработкиMPI-программ и настройки «головного» компьютера, с которого будетпроизводиться их запуск.
Менеджер работает в фоновомрежиме и ждёт запросов к нему из сети со стороны «головного» менеджерапроцессов (по умолчанию используется сетевой порт 8676). Чтобы обезопасить себяот хакеров и вирусов, менеджер требует пароль при обращении к нему.
Когда один менеджер процессовобращается к другому менеджеру процессов, он передаёт ему свой пароль.
Отсюда следует, что нужноуказывать один и тот же пароль при установке MPICH на компьютеры сети.
/>
Рис.4. Схема работы MPICH накластере.
В современных кластерах сетьпередачи данных обычно отделяется от управляющей сети.
Запуск MPI-программыпроизводится следующим образом (рис.4):
Пользователь с помощью программыMpirun (или Mpiexec, при использовании MPICH2 под Windows) указывает имяисполняемого файла MPI-программы и требуемое число процессов. Кроме того, можноуказать имя пользователя и пароль: процессы MPI-программы будут запускаться отимени этого пользователя.
Mpirun передаёт сведения о запускелокальному менеджеру процессов, у которого имеется список доступныхвычислительных узлов.
Менеджер процессов обращается квычислительным узлам по списку, передавая запущенным на них менеджерампроцессов указания по запуску MPI-программы.
Менеджеры процессов запускают навычислительных узлах несколько копий MPI-программы (возможно, по несколькокопий на каждом узле), передавая программам необходимую информацию для связидруг с другом.
Очень важным моментом здесьявляется то, что перед запуском MPI-программа не копируется автоматически навычислительные узлы кластера. Вместо этого менеджер процессов передаёт узлампуть к исполняемому файлу программы точно в том виде, в котором пользовательуказал этот путь программе Mpirun. Это означает, что если, например,запускается программа C: \program. exe, то все менеджеры процессов навычислительных узлах будут пытаться запустить файл C: \program. exe. Если хотябы на одном из узлов такого файла не окажется, произойдёт ошибка запуска MPI-программы.
Чтобы каждый раз не копироватьвручную программу и все необходимые для её работы файлы на вычислительные узлыкластера, обычно используют общий сетевой ресурс. В этом случаепользователь копирует программу и дополнительные файлы на сетевой ресурс,видимый всеми узлами кластера, и указывает путь к файлу программы на этомресурсе. Дополнительным удобством такого подхода является то, что при наличиивозможности записи на общий сетевой ресурс запущенные копии программы могутзаписывать туда результаты своей работы.
Работа MPI-программыпроисходит следующим образом:
Программа запускается и инициализируетбиблиотеку времени выполнения MPICH путём вызова функции MPI_Init.
Библиотека получает от менеджерапроцессов информацию о количестве и местоположении других процессов программы,и устанавливает с ними связь.
После этого запущенные копиипрограммы могут обмениваться друг с другом информацией посредством библиотеки MPICH.С точки зрения операционной системы библиотека является частью программы (работаетв том же процессе), поэтому можно считать, что запущенные копии MPI-программыобмениваются данными напрямую друг с другом, как любые другие приложения,передающие данные по сети.
Консольный ввод-вывод всехпроцессов MPI-программы перенаправляется на консоль, на которой запущена Mpirun.Насколько я понимаю, перенаправлением ввода-вывода занимаются менеджерыпроцессов, так как именно они запустили копии MPI-программы, и поэтому могутполучить доступ к потокам ввода-вывода программ.
Перед завершением все процессывызывают функцию MPI_Finalize, которая корректно завершает передачу и приёмвсех сообщений, и отключает MPICH.
Все описанные выше принципыдействуют, даже если вы запускаете MPI-программу на одном компьютере. 3.4 УстановкаMPICH в Windows
Необходимо загрузить последнююверсию MPICH2 со страницы www.mcs. anl.gov/research/projects/mpich2/downloads/index.php? s=downloads. Загруженный инсталлятор необходимо запустить с привилегиямиадминистратора на всех компьютерах, на которых планируется запуск MPI-программ.
Во время установки необходимоввести пароль для доступа к менеджеру процессов SMPD. Он должен быть одинаковыйна всех компьютерах:
/>
Рис.5. Указание пароля длядоступа к менеджеру процессов
В окне указания пути установкирекомендуется оставить каталог по умолчанию и выбрать пункт «Everyone»:
/>
Рис.6. Указание пути установки
Если Брандмауэр Windows спросит,разрешить ли доступ в сеть программе smpd. exe, то необходимо «Разрешить».
MPICH2 правильно установлен наваш компьютер.
Однако, прежде чем переходить к настройке,обязательно следует проверить две вещи: запущена ли служба «MPICH2 ProcessManager», и разрешён ли этой службе доступ в сеть.
/>
Рис.7. Служба «MPICH2Process Manager» в списке служб
/>
Рис.8. Программы MPICH в спискеисключений брандмауэра
Если какая-то из перечисленныхпрограмм отсутствует в списке разрешённых программ, то вы необходимо добавитьеё вручную. Соотвественно, C: \programfiles\mpich2\bin\mpiexec. exe, если отсутствует «Processlauncher for MPICH2 applications», и C: \program files\mpich2\bin\smpd. exe, если отсутствует «Processmanager service for MPICH2 applications».
3.5 Настройка MPICH
Рассмотрим настройку MPICH напримере конфигурации из двух компьютеров, объединённых в локальную сеть: одинкомпьютер имеет сетевое имя MrBig и IP-адрес 192.168.1.4, другой — имя Small и адрес192.168.1.3 MPI-программы планируется запускать с компьютера MrBIG. На обоихкомпьютерах установлены русскоязычные версии Windows. На MrBIG установленаWindows Vista, на Small — Windows XP. Каждый компьютер имеет двухъядерныйпроцессор.
Прежде всего необходимосоздать на всех компьютерах пользователя с одинаковым именем и паролем; отимени этого пользователя будут запускаться MPI-программы.
Wmpiregister
Как уже было сказано ранее,любое действие система MPICH выполняет от указанного имени пользователя.
Для того, чтобы спрашивать имяпользователя и пароль, используется программа Wmpiregister. Проблема в том, чтоимя пользователя и пароль спрашиваются достаточно часто.
Для того, чтобы этого избежать,Wmpiregister может сохранять имя пользователя и пароль в реестре Windows.
/>
Рис.9. Программа Wmpiregister
«Cancel» — закрытьпрограмму без выполнения какого-либо действия.
«OK» — передатьвведённые имя пользователя и пароль вызывающей программе.
«Remove» — нажатиеэтой кнопки удаляет сохранённые ранее имя пользователя и пароль из реестра Windows.
«Register» — сохраняетимя пользователя и пароль в реестре.
Wmpiconfig
Если все предыдущие шаги сделаныправильно, то в поле «version» в левой колонке таблицы будет написанаверсия установленного менеджера процессов (рис.10).
/>
Рис.10. Программа Wmpiconfig
Wmpiconfig предназначена длянастройки менеджеров процессов на текущем компьютере и других компьютерах сети.Для этого она подсоединяется к менеджерам процессов на выбранных компьютерах,читает имеющиеся у них настройки, и сообщает им новые настройки, если нужно. Элементыуправления программы Wmpiconfig выполняют следующие действия:
Слева-внизу имеется списоккомпьютеров, с которыми работает программа настройки. Имя компьютера на беломфоне означает, что не было попыток связаться с этим компьютером; зелёный фонозначает, что связь произведена успешно; серый фон означает, что приустановлении связи возникла ошибка. Удалить компьютер из списка можно клавишейDel. Следует иметь в виду, что этот список предназначен только для удобстванастройки, и не имеет никакого отношения к списку компьютеров, на которых будетзапущена MPI-программа.
Кнопка «Get Hosts» получаетсписок компьютеров в заданном домене или рабочей группе (задаётся в выпадающемсписке «Domain»). Полученный список заменяет имеющийся списоккомпьютеров или, если нажата кнопка "+", добавляет компьютеры к текущемусписку.
Кнопка «Scan Hosts» получаетнастройки со всех компьютеров списка; кнопка «Scan for Versions» получаеттолько номера версий.
Кнопка «Get Settings» получаеттекущие настройки того компьютера, имя которого введено в поле ввода «Host».При выборе компьютера в списке компьютеров его имя автоматически вводится вполе «Host». Если нажата кнопка «Click», то настройки будутполучены автоматически при выборе компьютера из списка.
Справа в окне расположенатаблица настроек. Пустое поле означает, что используется настройка поумолчанию, указанная во втором столбце. Настройки, предназначенные к изменению,следует отмечать установкой галочки слева.
Кнопка «Apply» применяетвыделенные галочкой настройки к тому компьютеру, имя которого находится в поле«Host». Кнопка «Apply All» применяет настройки ко всемкомпьютерам списка.
Кнопка «Cancel» закрываетпрограмму.
На том компьютере, с которогопланируется запуск программ, необходимо указать список доступныхвычислительных узлов. Этот список вводится через пробел в поле hosts левогостолбца таблицы (рисунок 11). На рисунке показан пример, когда сам компьютер, скоторого производится запуск MPI-программ, является одним из вычислительныхузлов.
/>
Рис.11. Список доступныхвычислительных узлов
3.6 Созданиеобщего сетевого ресурса
Для удобного запускаMPI-программ следует создать на одном из компьютеров общий сетевой ресурсс правом полного доступа для всех пользователей.
/>
Рис.12. Окно свойств папки
/>
Рис.13. Добавление разрешенийдля доступа к папке
3.7 ЗапускMPI-программ
Для запуска MPI-программ в комплектMPICH2 входит программа с графическим интерфейсом Wmpiexec, которая представляетсобой оболочку вокруг соответствующей утилиты командной строки Mpiexec. Графическийинтерфейс нагляднее консольного приложения, но в ряде случаев запуск Mpiexec изконсоли гораздо удобнее. Разницы для процесса вычисления нет, в любом случаеиспользуется Mpiexec.
/>
Рис.14. Программа Wmpiexec
Элементы управления окна имеют следующийсмысл:
Поле ввода «Application»:путь к MPI-программе. Как уже было сказано ранее, путь передаётся в неизменномвиде на все компьютеры сети, поэтому желательно, чтобы программа располагаласьв общей сетевой папке. Например, \\mrbig\mpi\mpi. exe.
«Number of processes»:число запускаемых процессов. По умолчанию процессы распределяются поровну междукомпьютерами сети, однако это поведение можно изменить при помощиконфигурационного файла.
Кнопка «Execute» запускаетпрограмму; кнопка «Break» принудительно завершает все запущенныеэкземпляры.
Флажок «run in a separatewindow» перенаправляет вывод всех экземпляров MPI-программы в отдельноеконсольное окно.
Кнопка «Show Command» показываетв поле справа командную строку, которая используется для запуска MPI-программы(напоминаю: Wmpiexec — всего лишь оболочка над Mpiexec). Командная строкасобирается из всех настроек, введённых в остальных полях окна.
Далее идёт большое текстовоеполе, в которое попадает ввод-вывод всех экземпляров MPI-программы, если не установленфлажок «run in a separate window».
Флажок «more options» показываетдополнительные параметры.
«working directory»: сюдаможно ввести рабочий каталог программы. Опять же, этот путь должен быть веренна всех вычислительных узлах. Если путь не указан, то в качестве рабочегокаталога будет использоваться место нахождения MPI-программы.
«hosts»: здесь можноуказать через пробел список вычислительных узлов, используемых для запускаMPI-программы. Если это поле пустое, то используется список, хранящийся в настройкахменеджера процессов текущего узла.
«environment variables»:в этом поле можно указать значения дополнительных переменных окружения,устанавливаемых на всех узлах на время запуска MPI-программы. Синтаксисследующий: имя1=значение1, имя2=значение2.
«drive mappings»: здесьможно указать сетевой диск, подключаемый на каждом вычислительном узле на времяработы MPI-программы. Синтакис: Z: \\winsrv\wdir.
«channel»: позволяетвыбрать способ передачи данных между экземплярами MPI-программы.
«extra mpiexec options»:в это поле можно ввести дополнительные ключи для командной строки Mpiexec.
Одним из наиболее полезныхдополнительных ключей является ключ -localonly, позволяющий эмулироватьвиртуальные вычислительные модули на одном компьютере. В случае с двухядернымпроцессором и двумя вычислительными процессами, процессы «раскидываются»на два ядра. Программа считается параллельно. Так как не тратится время напересылку пакетов по сети, то время вычислений на виртуальных вычислительныхмодулях на одном локальном процессоре превосходит время вычислений на реальныхмодулях. Таким образом, в большинстве случаев нет необходимости строитьлокальную сети обмена данными, а достаточно сэмулировать этот процесс.
Глава 4. Алгоритмы решения задачустойчивости для подкрепленных пологих оболочек, основанные нараспараллеливании процесса вычисления
При исследовании устойчивыхподкрепленных оболочек с учетом геометрической нелинейности приходитсямногократно решать системы алгебраических уравнений. Коэффициенты этихуравнений этих уравнений представляют собой двойные интегралы от громоздкихвыражений и их вычисление требует существенных затрат машинного времени. Чтобысократить это время используется процесс распараллеливания вычислений.
При использовании одного и тогоже набора аппроксимирующих функций, программа каждый раз производит большоеколичество вычислений интегралов от различных произведений этих функции. Количествотаких произведении пропорционально квадрату числа аппроксимирующих функций. Несмотря на это, программа производит, по сути, одни и те же вычисления. Вычислениеинтегралов является одной из самых длительных операций для ЭВМ. Учитывая, чтоэти действия многократно повторяются в циклах, эта часть вычислений становитсясамой долгой в контексте всего процесса вычисления.
Решить эту задачу можно путемзаготовки заранее вычисленных интегралов и сохранение их в отдельной базеданных (БД). Каждому набору аппроксимирующих функций будет соответствовать БД свычисленными интегралами. Главная задача будет состоять в построении правильнойвыборки значений для каждого количества аппроксимирующих членов. Схематичноэтот процесс показан ниже (табл.1).
Посторенние корректного запросаи его посылка в БД занимают гораздо меньше временных и процессорных ресурсов,чем вычисление интеграла. Из этого последует выигрыш по времени в 300-400% прирешении комплекса задач при различных параметрах (при различной кривизне итолщине оболочки, при различных величинах нагрузки).
Следующим шагом в ускорениивычислений является частичное распараллеливание процесса вычисления.
Для этого используется MPI.
Табл.1. Примерпроведения выборки из БД в зависимости от числа аппроксимирующих функцийN=4 N=9 N=16 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
Одно из главных правилоптимизации заключается в упрощении действий, выполняемых многократно в циклах.Логично было бы применить этот же принцип и для распараллеливания.Т. е. «рутинная»многократная работа будет разделена между определенным количеством процессоров.Так как нет смысла распараллеливать всю программу, можно выделить «головную»ЭВМ, которая будет выполнять основные шаги вычисления. Остальные же машиныбудут обрабатывать пакет задач, принимаемые от ведущей машины.Т. е. получаемсхему коммуникации процессоров, похожую на схему «клиент-сервер», заисключением того, что клиенты также могут обмениваться сообщениями, но толькопри согласовании своих действий с сервером (рис.14).
/>
Рис.14. Схема коммуникационнойсреды (ЦП — «головная» ЭВМ, П — «ведомая» ЭВМ)
Основные проблемы, которые могутвозникнуть в процессе распределенных вычислений:
некорректно сформированный пакетзадания или некорректный прием/сохранение результатов вычислений;
возникновение тупиковых ситуацийпри приеме/передаче сообщений между процессорами;
неправильное разделение заданиймежду процессорами.
Ведущая ЭВМ на этапах распараллеливаниябудет освобождена от выполнения «рутинных» вычислений. Взамен онабудет контролировать распределение заданий между ведомыми ЭВМ, фиксироватьтранзакции, отслеживать загруженность процессоров, принимать решение в случаевозникновения ошибок, перенаправлять задания / повторно высылать задания вслучае возникновения сбоя в среде коммуникации, собирать и проверять результатывычислений.
Данная схема рассчитана набольшое количество ЭВМ в коммуникационной среде.
На данном этапе для отработкисхем распараллеливания и расчета выигрыша по времени используются две ЭВМ сосхемой коммуникации типа «точка-точка», где обе машины являютсяравноправными.
Целью этой работы являетсясоздание программного интерфейса «PSS» (parallel solving for Shell) наоснове MPI, позволяющего, не обращаясь к низкоуровневым командам MPI,производить «прозрачное» распараллеливание вычислений. Таким образом,общая блок-схема программы не изменится, за исключением того, что отдельныеблоки в ней выполняются параллельно.
Ниже показана принципиальнаяблок-схема выполнения программы (рис.15). Блоки 2 и 6 можно производить вкоммуникационной среде посредством нескольких процессоров, используя интерфейсPSS. Блок 3 можно распараллелить при использовании метода Гаусса для решениясистем алгебраических уравнений.
Выигрыш по времени определяетсяследующими основными параметрами:
количество ЭВМ (процессоров) вкоммуникационной среде;
отношение части кода программы,пригодной для распараллеливания, ко всему объему кода программы;
степень сложности логикипроверки и контроля за вычислениями со стороны программного интерфейса PSS;
особенности аппаратной части (пропускнаяспособность канала, скорость чтения/записи, частота процессоров, …).
/>
Рис.15. Блок-схема выполненияпрограммы
Если мы будем использовать N ЭВМс одинаковой производительностью, то выигрыш по времени составит приблизительно(T/N) *1.3, где T — время выполнения программы на одном процессоре, а 1.3 — 30%-ая поправка, включающая в себя проверку и контроль со стороны PSS иособенности аппаратуры.
Все вышеуказанные положенияособенно важны, принимая во внимание исследовательский характер комплекса«Оболочка», что подразумевает проведение большого количествавычислений с использованием различных параметров оболочек, нагружений,закреплений, ребер и т.д. Поэтому даже небольшое ускорение процесса вычисленияодного эксперимента будет ощутимой экономией времени при многократном повтореэтого эксперимента.
4.1 Программаи результаты
Программа PSS была написана наязыке C с использованием MPI. Таким образом, возможна компиляция исходного кодана различных операционных системах и архитектурах, что делает программууниверсальной и кросс-платформенной[4]. Код программы представлен вПриложении 1.
После написания программы былиполучены серии результатов. Для каждого N (числа членов в разложении искомыхфункций) было проведено три эксперимента по замеру времени выполнения задачи:
Однопроцессорная система — одинпоследовательный процесс;
Две однопроцессорных системы,связанных Ethernet патчкордом со скоростью обмена данных 100 Мбит — двапараллельных процесса.
Одна однопроцессорнаядвухядерная система с общей памятью — два параллельных процесса.
В качестве тестовых систем былииспользованы следующие ПК:
Intel Core 2 Duo 2,0 Ггц, 2 Гбоперативной памяти;
Intel Xeon 2x2,66 Ггц, 4 Гбоперативной памяти.
Были получены следующиерезультаты: N
Последовательный
процесс, сек
Две однопроцессорные –
по одному ядру, сек
Одна однопроцессорная -
два ядра, сек Maple 12, сек 1 0.051569 0.061439 0.042440 0.8 4 2.124557 0.779514 0.611919 2.9 9 5.022527 3.339019 3.080036 7.8 16 12.646657 10.744853 9.732358 13.0 25 31.078364 26.457036 23.840874 38.6 121 770.707305 644.396220 586.622127 952.3
/>
/>
/>
Заключение
При исследовании устойчивостиподкрепленных оболочек с учетом геометрической и физической нелинейности припоследовательном вычислении требуется достаточно большое время для расчетаодного варианта — до нескольких часов. Расчеты, проведенные с помощью ПК Ansys,показали, что на подготовку входных данных и расчет варианта также требуетсянесколько часов. Таким образом, при распараллеливании процессов вычислениявремя расчета одного варианта существенно сокращается, что позволит проводитьвычисления самой «затратной» задачи максимум в течение часа, акритические нагрузки при линейно-упругом деформировании в течение несколькихминут.
Работа докладывалась на седьмойвсероссийской конференции «Математическое моделирование и краевые задачи (ММ-2010)»,проходившей 3-6 июня 2010 в г. Самара. Получила одобрение и положительныеотзывы от оргкомитета и участников конференции.
Литература
1. Антонов А.С. Параллельное программирование с использованием технологииMPI — М.: Изд-во МГУ, 2004. — 71 с.
2. Бондаренко В.М., Бондаренко С.В. Инженерные методы нелинейной теориижелезобетона. — М.: Стройиздат, 1982. — 288 с.
3. Васильев А.Н. Самоучитель C++ с задачами и примерами — М.: Наука иТехника, 2010. — 480 с.
4. Воеводин В.В. Вычислительная математика и структура алгоритмов — М.:Изд-во МГУ, 2006. — 112 с.
5. Воеводин В.В. Математические модели и методы в параллельных процессах — М.: Наука. Гл. ред. физ. — мат. лит., 1986. — 296 с.
6. Воеводин В.В., Воеводин Вл.В. Параллельные вычисления — СПб.:БХВ-Петербург, 2002. — 608 с.
7. Воеводин Вл.В., Жуматий С.А. Вычислительное дело и кластерные системы — М.: Изд-во МГУ, 2007. — 150 с.
8. Жгутов В.М. Математические модели и алгоритмы исследования устойчивостипологих ребристых оболочек при учете различных свойств материала // ИзвестияОрловского гос. техн. ун-та. Серия «Строительство, транспорт». — 2007. №4. — С. 20-23.
9. Ильюшин А.А. Пластичность. М.: Гостехиздат. 1948. — 376 с.
10. Карпов В.В. Математическое моделирование, алгоритмы исследования модели,вычислительный эксперимент в теории оболочек: учеб. пособие — СПб.: СПбГАСУ,2006. — 330 с.
11. Карпов В.В., Баранова Д.А., Беркалиев Р.Т. Программный комплексисследования устойчивости оболочек — СПб.: СПбГАСУ, 2009. — 102 с.
12. Карпов В.В., Сальников А.Ю. Вариационные методы и вариационные принципымеханики при расчете строительных конструкций: учеб. пособие — СПб.: СПбГАСУ,2009. — 75 с.
13. Керниган Б, Ритчи Д. Язык программирования C — М.: Вильямс, 2009. — 304с.
14. Климанов В.И., Тимашев С.А. Нелинейные задачи подкрепленных оболочек.Свердловск: УНЦ АН СССР, 1985. — 291 с.
15. Петров В.В., Овчинников И.Г., Ярославский В.И. Расчет пластинок иоболочек из нелинейно-упругого материала. — Саратов: Изд-во Сарат. ун-та, 1976.- 136 с.
16. Хьюз К., Хьюз Т. Параллельное и распределенное программирование сиспользованием C++ — М.: Вильямс, 2004. — 672 с.
Приложения
Приложение 1. Код программы
Main. cpp:
/*
Main. cpp
Сизов А.С. ПМ5
2010 г.
*/
// Подключение необходимых заголовочныхфайлов
#include «mpi. h» // библиотекаmpi
#include
/*
stdio. h (отангл. standard input/output header -
стандартный заголовочный файлввода/вывода) заголовочный файл
стандартной библиотеки языка Си,содержащий определения макросов,
константы и объявления функций итипов, используемых для различных
операций стандартного ввода ивывода. Функциональность унаследована
от «портативного пакетаввода/вывода» («portable I/O package»),
написанного Майком Леском изBell Labs в начале 1970-х.
Функции, объявленные в stdio. h,являются весьма популярными благодаря тому,
что являясь частью Стандартнойбиблиотеки языка Си, они гарантируют работу
на любой платформе,поддерживающей Си. Приложения на отдельных платформах
могут, тем не менее, иметьпричины для использования функций ввода/вывода
самой платформы вместо функцийstdio. h.
*/
#include
/*
stdlib. h — заголовочный файлстандартной библиотеки
общего назначения языка Си,который содержит в себе функции,
занимающиеся выделением памяти,контроль процесса выполнения программы,
преобразования типов и другие.
*/
#include
/*
math. h — заголовочный файлстандартной библиотеки языка программирования С,
разработанный для выполненияпростых математических операций. Большинство
функций привлекают использованиечисел с плавающей точкой. Все эти функции
принимают double, если неопределено иначе. Для работы с типами float и
long double используются функциис постфиксами f и l соответственно.
Все функции, принимающие иливозвращающие угол, работают с радианами.
*/
#include «matrix. h»
/*
matrix. h — заголовочный файлбиблиотеки, содержащей определения
класса матрицы matrix,использованного в дальнейшем в программе.
Содержит объявление класса,методы для работы с ним, такие как:
произведение матрицы на матрицу;
сложение матрицы с матрицей;
выделение памяти под матрицу;
выгрузка данных;
загрузка данных;
копирование матрицы;
сравнение полученной единичнойматрицы с эталоном единичной матрицы;
обращение матрицы.
*/
// Объявление переменных
double *X1, *X2, *X3, *Y1, *Y2,*Y3; // Коэффициенты аппроксимирующих // функций
double *C1, *C2; // Коэффициентысистемы
int N, n, m, E;
double q, h,mu, r, Pi, mu1, Kx, Ky, R1, R2, W;
double a,b;
/*
N — количество членов вприближении по методу Ритца;
n — количество ребер по x;
m — количество ребер по y;
E — модуль упругости материала;
q — поперечнаяравномерно-распределенная нагрузка;
h — толщина оболочки;
mu — коэффициент Пуассона;
r — ширина ребер;
Pi — число Пи;
R1 — радиус кривизны по x;
R2 — радиус кривизны по y;
a — длина оболочки по x;
b — длина оболочки по y;
*/
// Процедуры вычисленияпроизводных функций
double sin_0 (double k, double x)
{
return sin (k *x);
}
double sin_1 (doublek, double x) // первая производная
{
return k * cos(k * x);
}
double sin_2 (doublek, double x) // вторая производная
{
return — k * k* sin (k * x);
}
double Fx (intk, int i, int j, double arg) // выборка произведений
{ // аппроксимирующих
switch (k) // функций для х
{
case 1:
return sin_1 (X1[i], arg) * sin_1 (X1 [j], arg);
case 2:
return sin_0 (X1[i], arg) * sin_0 (X1 [j], arg);
case 3:
return sin_1 (X1[i], arg) * sin_0 (X2 [j], arg);
case 4:
return sin_0 (X1[i], arg) * sin_1 (X2 [j], arg);
case 5:
return sin_1 (X1[i], arg) * sin_0 (X3 [j], arg);
case 6:
return sin_0 (X2[i], arg) * sin_0 (X2 [j], arg);
case 7:
return sin_1 (X2[i], arg) * sin_1 (X2 [j], arg);
case 8:
return sin_0 (X2[i], arg) * sin_0 (X3 [j], arg);
case 9:
return sin_0 (X3[i], arg) * sin_1 (X1 [j], arg);
case 10:
return sin_0 (X3[i], arg) * sin_0 (X3 [j], arg);
case 11:
return sin_2 (X3[i], arg) * sin_2 (X3 [j], arg);
case 12:
return sin_2 (X3[i], arg) * sin_0 (X3 [j], arg);
case 13:
return sin_1 (X3[j], arg) * sin_1 (X3 [j], arg);
case 14:
return sin_0 (X3[j], arg);
default:
return 0;
}
}
doublesimpsonFx (double a, double b, int k, int i, int j)
{ // метод Симпсона для х
int n = 1000;
double locI, h,xi, s1 = 0.0, s2 = 0.0, y [10000] ;
int f;
h = (b — a) / n;
xi = a;
for (f = 0; f
{
y [f] = Fx (k,i,j,xi);
xi = xi + h/2;
}
locI = y [0] +y [2*n] ;
for (f = 2; f
s1 = s1 + y [f];
for (f = 1; f
s2 = s2 + y [f];
locI = (locI +2.0 * s1 + 4.0 * s2) * (h / 6);
return (locI);
}
double Fy (intk, int i, int j, double arg) // выборка произведений
{ // аппроксимирующих
switch (k) // функций для y
{
case 1:
return sin_0 (Y1[i], arg) * sin_0 (Y1 [j], arg);
case 2:
return sin_1 (Y1[i], arg) * sin_1 (Y1 [j], arg);
case 3:
return sin_0 (Y1[i], arg) * sin_1 (Y2 [j], arg);
case 4:
return sin_1 (Y1[i], arg) * sin_0 (Y2 [j], arg);
case 5:
return sin_0 (Y1[i], arg) * sin_0 (Y3 [j], arg);
case 6:
return sin_1 (Y2[i], arg) * sin_1 (Y2 [j], arg);
case 7:
return sin_0 (Y2[i], arg) * sin_0 (Y2 [j], arg);
case 8:
return sin_1 (Y2[i], arg) * sin_0 (Y3 [j], arg);
case 9:
return sin_0 (Y3[i], arg) * sin_0 (Y1 [j], arg);
case 10:
return sin_0 (Y3[i], arg) * sin_0 (Y3 [j], arg);
case 11:
return sin_2 (Y3[i], arg) * sin_2 (Y3 [j], arg);
case 12:
return sin_2 (Y3[i], arg) * sin_0 (Y3 [j], arg);
case 13:
return sin_1 (Y3[i], arg) * sin_1 (Y3 [j], arg);
case 14:
return sin_0 (Y3[j], arg);
default:
return 0;
}
}
doublesimpsonFy (double a, double b, int k, int i, int j)
{ // метод Симпсона для y
int n = 1000;
double locI, h,xi, s1 = 0.0, s2 = 0.0, y [10000] ;
int f;
h = (b — a) / n;
xi = a;
for (f = 0; f
{
y [f] = Fy (k,i,j,xi);
xi = xi + h/2;
}
locI = y [0] +y [2*n] ;
for (f = 2; f
s1 = s1 + y [f];
for (f = 1; f
s2 = s2 + y [f];
locI = (locI +2.0 * s1 + 4.0 * s2) * (h / 6);
return (locI);
}
double C (intk, int i, int j) // коэффициэнты в ФПЭД
{
switch (k)
{
case 1:
return2*h*simpsonFx (0.0,a,1, i,j) *simpsonFy (0.0,a,1, i,j) +2*mu1*h*simpsonFx (0.0,a,2,i,j) *simpsonFy (0.0,a,2, i,j);
case 2:
return2*h*mu*simpsonFx (0.0,a,3, i,j) *simpsonFy (0.0,a,3, i,j) +2*mu1*h*simpsonFx (0.0,a,4,i,j) *simpsonFy (0.0,a,4, i,j);
case 3:
return — 2*h* (Kx+mu*Ky)*simpsonFx (0.0,a,5, i,j) *simpsonFy (0.0,a,5, i,j);
case 4:
return2*h*mu*simpsonFx (0.0,a,3, i,j) *simpsonFy (0.0,a,3, i,j) +2*mu1*h*simpsonFx (0.0,a,4,i,j) *simpsonFy (0.0,a,4, i,j);
case 5:
return2*h*simpsonFx (0.0,a,6, i,j) *simpsonFy (0.0,a,6, i,j) +2*mu1*h*simpsonFx (0.0,a,7,i,j) *simpsonFy (0.0,a,7, i,j);
case 6:
return — 2*h* (mu*Kx+Ky)*simpsonFx (0.0,a,8, i,j) *simpsonFy (0.0,a,8, i,j);
case 7:
return — 2*h* (Kx+mu*Ky)*simpsonFx (0.0,a,9, i,j) *simpsonFy (0.0,a,9, i,j);
case 8:
return — 2*h* (mu*Kx+Ky)*simpsonFx (0.0,a,8, i,j) *simpsonFy (0.0,a,8, i,j);
case 9:
return 2*h* (Kx*Kx+2*mu*Kx*Ky+Ky*Ky)*simpsonFx (0.0,a,10, i,j) *simpsonFy (0.0,a,10, i,j) +pow (h,3) /12
* (2*simpsonFx(0.0,a,11, i,j) *simpsonFy (0.0,a,10, i,j) +2*mu*simpsonFx (0.0,a,12, i,j)
*simpsonFy (0.0,a,12,i,j) +2*mu*simpsonFx (0.0,a,12, i,j) *simpsonFy (0.0,a,12, i,j) +2*simpsonFx (0.0,a,10,i,j)
*simpsonFy (0.0,a,11,i,j) +8*mu1*simpsonFx (0.0,a,13, i,j) *simpsonFy (0.0,a,13, i,j));
case 10:
return 2* (1-pow(mu,2)) *simpsonFx (0.0,a,14, i,j) *simpsonFy (0.0,a,14, i,j);
default:
return 0;
}
}
int main (intargc,char *argv [])
{
// объявление переменных.
int myid, numprocs;
int namelen;
charprocessor_name [MPI_MAX_PROCESSOR_NAME] ;
doublestartwtime = 0.0, endwtime;
int rc;
MPI_Statusstatus;
rc = MPI_Init (&argc,&argv);
rc|=MPI_Comm_size (MPI_COMM_WORLD,&numprocs);
rc|=MPI_Comm_rank (MPI_COMM_WORLD,&myid);
if (rc! = 0)
printf («errorinitializing MPI and obtaining task ID information\n»);
MPI_Get_processor_name(processor_name,&namelen);
fprintf (stdout,«Process%dof%d is on%s\n»,
myid, numprocs,processor_name);
fflush (stdout);
// функцияначала замера времени вычисления.
if (myid == 0) {
startwtime =MPI_Wtime ();
}
N = 4; // количество членов
a = 1, b = 1;
n = 6, m = 6, E= 21000;
q = 0.0037, h =0.001, mu = 0.3, r = 0.2;
Pi = 3.14;
int i, j;
double rv;
bool xyz;
R1 = 440*h;
R2 = 440*h;
mu1 = (1-mu) /2;
Kx = 1/ (double)R1;
Ky = 1/ (double) R2;
// выделение памяти под массивыдля аппроксимирующих функций
X1 = (double*) malloc(N * sizeof (double));
X2 = (double*) malloc(N * sizeof (double));
X3 = (double*) malloc(N * sizeof (double));
Y1 = (double*) malloc(N * sizeof (double));
Y2 = (double*) malloc(N * sizeof (double));
Y3 = (double*) malloc(N * sizeof (double));
int sqrtN = pow (N, 0.5);
/*
вычисление коэффициентов аппроксимирующихфункций на
нескольких процессах.
*/
for (i = 1; i
{
for (j = 1; j
{
if (myid == 0) {
X1 [sqrtN * (i- 1) + j — 1] = 2 * i * Pi;
printf («X1[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,X1 [sqrtN * (i — 1) + j — 1]);
X2 [sqrtN * (i- 1) + j — 1] = (2 * i — 1) * Pi;
printf («X2[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,X2 [sqrtN * (i — 1) + j — 1]);
X3 [sqrtN * (i- 1) + j — 1] = (2 * i — 1) * Pi;
printf («X3[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,X3 [sqrtN * (i — 1) + j — 1]);
}
if (myid == 1) {
Y1 [sqrtN * (i- 1) + j — 1] = (2 * j — 1) * Pi;
printf («Y1[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,Y1 [sqrtN * (i — 1) + j — 1]);
Y2 [sqrtN * (i- 1) + j — 1] = 2 * j * Pi;
printf («Y2[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,Y2 [sqrtN * (i — 1) + j — 1]);
Y3 [sqrtN * (i- 1) + j — 1] = (2 * j — 1) * Pi;
printf («Y3[%d] =%.3f\n»,sqrtN * (i — 1) + j — 1,Y3 [sqrtN * (i — 1) + j — 1]);
}
}
}
/*
пересылка результатов вычисленийна «головную» машину
*/
if (myid == 1) {
MPI_Send (Y1,N, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
MPI_Send (Y2,N, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD);
MPI_Send (Y3,N, MPI_DOUBLE, 0, 3, MPI_COMM_WORLD);
MPI_Recv (X1,N, MPI_DOUBLE, 0, 4, MPI_COMM_WORLD,
&status);
MPI_Recv (X2,N, MPI_DOUBLE, 0, 5, MPI_COMM_WORLD,
&status);
MPI_Recv (X3,N, MPI_DOUBLE, 0, 6, MPI_COMM_WORLD,
&status);
}
if (myid == 0) {
MPI_Recv (Y1,N, MPI_DOUBLE, 1, 1, MPI_COMM_WORLD,
&status);
MPI_Recv (Y2,N, MPI_DOUBLE, 1, 2, MPI_COMM_WORLD,
&status);
MPI_Recv (Y3,N, MPI_DOUBLE, 1, 3, MPI_COMM_WORLD,
&status);
MPI_Send (X1,N, MPI_DOUBLE, 1, 4, MPI_COMM_WORLD);
MPI_Send (X2,N, MPI_DOUBLE, 1, 5, MPI_COMM_WORLD);
MPI_Send (X3,N, MPI_DOUBLE, 1, 6, MPI_COMM_WORLD);
}
// вывод времени вычисленияаппрокс. функций
if (myid == 0) {
endwtime =MPI_Wtime ();
printf ("\nappfunc clock time =%f\n", endwtime-startwtime);
}
printf ("\n — — - BEGIN — -----------------\n");
/*
выделение памяти под массивыкоэффициентов ФПЭД
и вычисление их на разныхпроцессах.
*/
C1 = (double*) malloc(3 * N * 3 * N * sizeof (double));
C2 = (double*) malloc(3 * N * 3 * N * sizeof (double));
for (i = 0; i
{
for (j = 0; j
{
// обнуление всех значений дляудобства пересылки
C1 [i*N+j] =0;
C1 [i*N+N+j] =0;
C1 [i*N+2*N+j] =0;
C1 [N+i*N+j] =0;
C1 [N+i*N+N+j] =0;
C1 [N+i*N+2*N+j]=0;
C1 [2*N+i*N+j] =0;
C1 [2*N+i*N+N+j]=0;
C1 [2*N+i*N+2*N+j]=0;
if (myid == 0) {
C1 [N*i+j] =C (1,i,j);
C1 [N*i+N+j] =C(2, i,j);
C1 [N*i+2*N+j] =C(3, i,j);
C1 [N+N*i+j] =C(4, i,j);
C1 [N+N*i+N+j] =C(5, i,j);
}
if (myid == 1) {
C1 [N+N*i+2*N+j]=C (6, i,j);
C1 [2*N+N*i+j] =C(7, i,j);
C1 [2*N+N*i+N+j]=C (8, i,j);
C1 [2*N+N*i+2*N+j] =C (9, i,j);
}
}
}
// пересылка массивов на «головную»машину
if (myid == 1) {
MPI_Send (C1,3*N*3*N, MPI_DOUBLE, 0, 7, MPI_COMM_WORLD);
}
if (myid == 0) {
MPI_Recv (C2,3*N*3*N, MPI_DOUBLE, 1, 7, MPI_COMM_WORLD, &status);
printf ("\n\nC2[1]%.3f\n",C2 [0]);
}
printf ("\n- — — END — -----------------\n");
if (myid == 0) {
matrix M1 (3*N,3*N);
printf ("--------------------- BEGIN FIRST — -----------------\n");
for (i = 0; i
{
for (j = 0; j
{
M1. setvalue (i,j,C(1, i,j));
printf («C1[%d,%d]: =%.5f », i,j,C (1, i,j));
M1. setvalue (i,N+j,C(2, i,j));
printf («C2[%d,%d]: =%.5f », i,N+j,C (2, i,j));
M1. setvalue (i,2*N+j,C(3, i,j));
printf («C3[%d,%d]: =%.5f\n», i,2*N+j,C (3, i,j));
M1. setvalue (N+i,j,C(4, i,j));
printf («C4[%d,%d]: =%.5f »,N+i,j,C (4, i,j));
M1. setvalue (N+i,N+j,C(5, i,j));
printf («C5[%d,%d]: =%.5f »,N+i,N+j,C (5, i,j));
M1. setvalue (N+i,2*N+j,C(6, i,j));
printf («C6[%d,%d]: =%.5f\n»,N+i,2*N+j,C (6, i,j));
M1. setvalue (2*N+i,j,C(7, i,j));
printf («C7[%d,%d]: =%.5f »,2*N+i,j,C (7, i,j));
M1. setvalue (2*N+i,N+j,C(8, i,j));
printf («C8[%d,%d]: =%.5f »,2*N+i,N+j,C (8, i,j));
M1. setvalue (2*N+i,2*N+j,C(9, i,j));
printf («C9[%d,%d]: =%.5f\n»,2*N+i,2*N+j,C (9, i,j));
}
}
printf ("--------------------- END FIRST — -----------------\n");
printf ("--------------------- BEGIN SECOND — -----------------\n");
for (i = 0; i
{
for (j = 0; j
{
M1. setvalue (i,j,C1[N*i+j]);
printf («C1[%d,%d]: =%.5f », i,j,C1 [N*i+j]);
M1. setvalue (i,N+j,C1[N*i+N+j]);
printf («C2[%d,%d]: =%.5f », i,N+j,C1 [N*i+N+j]);
M1. setvalue (i,2*N+j,C1[N*i+2*N+j]);
printf («C3[%d,%d]: =%.5f\n», i,2*N+j,C1 [N*i+2*N+j]);
M1. setvalue (N+i,j,C1[N+i+j]);
printf («C4[%d,%d]: =%.5f »,N+i,j,C1 [N+N*i+j]);
M1. setvalue (N+i,N+j,C1[N+N*i+N+j]);
printf («C5[%d,%d]: =%.5f »,N+i,N+j,C1 [N+N*i+N+j]);
M1. setvalue (N+i,2*N+j,C2[N+N*i+2*N+j]);
printf («C6[%d,%d]: =%.5f\n»,N+i,2*N+j,C2 [N+N*i+2*N+j]);
M1. setvalue (2*N+i,j,C2[2*N+N*i+N+j]);
printf («C7[%d,%d]: =%.5f »,2*N+i,j,C2 [2*N+N*i+N+j]);
M1. setvalue (2*N+i,N+j,C2[2*N+N*i+N+j]);
printf («C8[%d,%d]: =%.5f »,2*N+i,N+j,C2 [2*N+N*i+N+j]);
M1. setvalue (2*N+i,2*N+j,C2[2*N+N*i+2*N+j]);
printf («C9[%d,%d]: =%.5f\n»,2*N+i,2*N+j,C2 [2*N+N*i+2*N+j]);
}
}
printf ("--------------------- END SECOND — -----------------\n");
// заполнение массивовсвободных членов
matrix Pow (3*N,3*N);
for (i=0; i
{
for (j=0; j
{
Pow. setvalue (i,j,0);
}
}
for (i = 0; i
{
Pow. setvalue (i,0,0);
Pow. setvalue (N+i,0,0);
Pow. setvalue (2*N+i,0,q/E*C(10, i,0));
}
printf ("\n\n\nM1:");
for (i=0; i
{
printf ("\n%d:", i);
for (j=0; j
{
M1. getvalue (i,j,rv,xyz);
printf ("%.10f ",rv);
}
}
// выделение памяти под матрицы
matrix M2 (3*N,3*N);
matrix M3 (3*N,3*N);
// копированиематрицы коэффициентов
M2. copymatrix (M1);
// обращение матрицы
M1. invert ();
// произведение матриц
M3. settoproduct (M1,M2);
// сравнение полученнойединичной матрицы с эталоном единичной матрицы
M3.comparetoidentity();
printf ("\n\n\ninverse:");
for (i=0; i
{
printf ("\n%d:", i);
for (j=0; j
{
M3. getvalue (i,j,rv,xyz);
printf ("%.10f",rv);
}
}
for (i=0; i
{
printf ("\n%d:", i);
for (j=0; j
{
M1. getvalue (i,j,rv,xyz);
printf ("%.10f ",rv);
}
}
// выделение памяти для матрицырезультатов
matrix Ans (3*N,3*N);
Ans. settoproduct(M1,Pow);
printf ("\nanswer\n");
for (i=0; i
{
printf ("%d:", i);
Ans. getvalue (i,0,rv,xyz);
printf ("%.10f", rv);
printf ("\n");
}
// выводрезультата
W = 0;
for (i = 0; i
{
Ans. getvalue (2*N+i,0,rv,xyz);
printf("!!%.10f%.10f%.10f\n", rv, X3 [i], Y3 [i]);
W += rv * sin_0(X3 [i],a/2) * sin_0 (Y3 [i],a/2);
}
printf («W: =%.10f», W);
// вывод времени вычисленияпрограммы
endwtime =MPI_Wtime ();
printf ("\nwallclock time =%f\n", endwtime-startwtime);
fflush (stdout);
}
MPI_Finalize();
return 0;
}
Matrix. h:
#ifndef__mjdmatrix_h
#define__mjdmatrix_h
template class matrix{
int maxsize;
int actualsize;
D* data;
void allocate() {
delete [] data;
data = new D [maxsize*maxsize];
};
matrix () {};
matrix (intnewmaxsize) {matrix (newmaxsize,newmaxsize); };
public:
matrix (intnewmaxsize, int newactualsize) {
if (newmaxsize
maxsize =newmaxsize;
if ( (newactualsize0))
actualsize =newactualsize;
else
actualsize =newmaxsize;
data = 0;
allocate ();
};
~matrix () {delete [] data; };
voidsettoproduct (matrix& left, matrix& right) {
actualsize =left. getactualsize ();
if (maxsize
maxsize = left.getactualsize ();
allocate ();
}
for (int i = 0;i
for (int j = 0;j
D sum = 0.0;
D leftvalue,rightvalue;
bool success;
for (int c = 0;c
left. getvalue(i,c,leftvalue,success);
right. getvalue(c,j,rightvalue,success);
sum +=leftvalue * rightvalue;
}
setvalue (i,j,sum);
}
}
void combine (matrix&left, matrix& right) {
actualsize =left. getactualsize ();
if (maxsize
maxsize = left.getactualsize ();
allocate ();
}
for (int i = 0;i
for (int j = 0;j
D sum = 0.0;
D leftvalue,rightvalue;
bool success;
left. getvalue(i,j,leftvalue,success);
right. getvalue(i,j,rightvalue,success);
sum = leftvalue+ rightvalue;
setvalue (i,j,sum);
}
}
voidsetactualsize (int newactualsize) {
if (newactualsize> maxsize)
{
maxsize =newactualsize;
allocate ();
}
if (newactualsize>= 0) actualsize = newactualsize;
};
intgetactualsize () { return actualsize; };
void getvalue (introw, int column, D& returnvalue, bool& success) {
if ( (row>=maxsize)|| (column>=maxsize)
|| (row
{ success =false;
return; }
returnvalue =data [row * maxsize + column] ;
success = true;
};
bool setvalue (introw, int column, D newvalue) {
if ( (row >=maxsize) || (column >= maxsize)
|| (row
data [row *maxsize + column] = newvalue;
return true;
};
voiddumpMatrixValues () {
bool xyz;
double rv;
for (int i=0; i
{
std:: cout
for (int j=0; j
{
M. getvalue (i,j,rv,xyz);
std:: cout
}
std:: cout
}
};
voidcomparetoidentity () {
intworstdiagonal = 0;
Dmaxunitydeviation = 0.0;
Dcurrentunitydeviation;
for (int i = 0;i
currentunitydeviation= data [i*maxsize+i] — 1.;
if (currentunitydeviation
if (currentunitydeviation> maxunitydeviation) {
maxunitydeviation= currentunitydeviation;
worstdiagonal =i;
}
}
intworstoffdiagonalrow = 0;
intworstoffdiagonalcolumn = 0;
Dmaxzerodeviation = 0.0;
Dcurrentzerodeviation;
for (int i = 0;i
for (int j = 0;j
if (i == j) continue;
currentzerodeviation= data [i*maxsize+j] ;
if (currentzerodeviation
if (currentzerodeviation> maxzerodeviation) {
maxzerodeviation= currentzerodeviation;
worstoffdiagonalrow= i;
worstoffdiagonalcolumn= j;
}
}
}
printf («Worstdiagonal value deviation from unity:%0.5f at row/column%0.3f\n», maxunitydeviation,worstdiagonal);
printf («Worstoff-diagonal value deviation from zero:%0.5f at row%0.3f, column%0.3f\n», maxzerodeviation,worstoffdiagonalrow,worstoffdiagonalcolumn);
};
void copymatrix(matrix& source) {
actualsize =source. getactualsize ();
if (maxsize
maxsize =source. getactualsize ();
allocate ();
}
for (int i = 0;i
for (int j = 0;j
D value;
bool success;
source. getvalue(i,j,value,success);
data [i*maxsize+j]= value;
}
};
void invert () {
if (actualsize
if (actualsize== 1) return;
for (int i=1; i
for (int i=1; i
for (int j=i; j
D sum = 0.0;
for (int k = 0;k
sum += data [j*maxsize+k]* data [k*maxsize+i] ;
data [j*maxsize+i]- = sum;
}
if (i ==actualsize-1) continue;
for (int j=i+1;j
D sum = 0.0;
for (int k = 0;k
sum += data [i*maxsize+k]*data [k*maxsize+j] ;
data [i*maxsize+j]=
(data [i*maxsize+j]-sum) / data [i*maxsize+i] ;
}
}
for (int i = 0;i
for (int j = i;j
D x = 1.0;
if (i! = j) {
x = 0.0;
for (int k = i;k
x — = data [j*maxsize+k]*data [k*maxsize+i] ;
}
data [j*maxsize+i]= x / data [j*maxsize+j] ;
}
for (int i = 0;i
for (int j = i;j
if (i == j) continue;
D sum = 0.0;
for (int k = i;k
sum += data [k*maxsize+j]* ( (i==k)? 1.0: data [i*maxsize+k]);
data [i*maxsize+j]= — sum;
}
for (int i = 0;i
for (int j = 0;j
D sum = 0.0;
for (int k = ((i>j)? i: j); k
sum += ( (j==k)?1.0: data [j*maxsize+k]) *data [k*maxsize+i] ;
data [j*maxsize+i]= sum;
}
};
};
#endif