Установите необходимое программное обеспечение (компиляторы C, C++, Cilk, среду LAM-MPI). Для выполнения заданий с процессами и нитями ознакомьтесь с примерами программ из соответствующих разделов книги Богачева [1], для выполнения задания Б, - с использованием MPI, рассмотрите примеры из [3] и [4], а также пример выполнения задания, приведенный далее. В случае невозможности организовать виртуальную параллельную машину из реальных компьютеров использовать виртуальные машины на основе VirtualBox или VMWare с установкой на них соответствующего программного обеспечения.
Контрольная работа выполняется по вариантам, и состоит из двух разрабатываемых программ, A и Б. Номер вариант вычисляется как остаток от деления номера зачетной книжки на 7 плюс один. Если полученная цифра больше 7 - делим еще раз на 7 плюс один.
Задание A.
Вычислить двукратный интеграл , пределы интегрирования по x от a до b, по y от c до d, число интервалов разбиения по x и по y задано числом N, N>10000; использовать метод параллелепипедов, вычисляя объем i,j-го параллелепипеда по формуле
Построить график зависимости времени выполнения расчета от количества параллельных задач (глубины рекурсии в варианте 6) для многоядерного процессора. Для измерения времени вычислений использовать функцию gettimeofday, позволяющую измерять время с точностью до микросекунд.
Варианты заданий: написать программу
1. с использованием Cilk
2. с использованием процессов и передачей данных через канал,
3. с использованием процессов и передачей данных через разделяемую память
4. с использованием процессов и передачей данных через именованный канал
5. с использованием нитей и передачей данных через глобальные переменные
6. с использованием нитей и рекурсивного способа декомпозиции
7. с использованием нитей и способа декомпозиции по данным
Задание Б.
Написать программу, моделирующую одноатомный газ, состоящий из одинаковых молекул с массой m и радиусом r, заключенных в кубический сосуд. Центр сосуда совпадает с началом координат. Соударениями молекул пренебречь, столкновения со стенками сосуда считать абсолютно упругими. Каждый процесс рассчитывает отдельную область пространства сосуда, передавая данные о молекуле соседнему процессу в случае перехода молекулы в его область. Начальные данные — случайные значения координат молекул и скорости задаются в головном процессе и доставляются с использованием MPI и широковещательных способов передачи данных. Выходными данными являются: количество соударений молекул со стенками сосуда и переданный стенкам импульс за единицу времени.
Выполнить разработку, используя в качестве исходных данных начальные условия по вариантам:
1. количество молекул 10000, все сосредоточены в 1/8 части объема, в первом октанте, имеют случайные значения координат и скоростей (от 0 до 400 м/сек).
2. количество молекул 10000, распределены по всему объему, имеют случайные значения координат и скоростей (от 0 до 400 м/сек).
3. количество молекул 10000, все сосредоточены в 1/2 части объема, с положительными значениями координаты x, имеют случайные значения координат и скоростей (от 0 до 400 м/сек).
4. количество молекул 10000, распределены по всему объему, имеют случайные значения координат и одинаковые по модулю (300 м/сек), но случайные по направлению скорости.
5. количество молекул 10000, распределены по двум диаметрально расположенным октантам, имеют случайные значения координат и скоростей (от 0 до 400 м/сек).
6. количество молекул 10000, все распределены по объему равномерно, но в 1/8 части объема, в первом октанте, имеют значения скоростей от 300 до 600 м/сек, в то время как в оставшемся объеме — скорости от 0 до 400 м/сек.
7. количество молекул 10000, все сосредоточены в 1/8 части объема, в первом октанте, имеют одинаковые по модулю значения скоростей, 400 м/сек, но случайные по направлению.
Построить график изменения давления на отдельные стенки сосуда от времени.
Пример составления и запуска MPI-приложения.
Рассмотрим пример использования MPI для решения задачи однократного численного интегрирования методом трапеций. Подготовим исходный файл prog.c:
#include <stdio.h>
#include <math.h>
#include "mpi.h"
main(int argc, char** argv) {
int my_rank; /* номер текущего задания */
int p; /* количество заданий */
double a; /* начало интервала интегр. */
double b; /* верний предел интегр. */
int n; /* количество подинтервалов */
double h; /* ширина интервала */
double local_a; /* нижний предел для задания */
double local_b; /* верхний предел для задания*/
int local_n; /* количество интервалов для */
/* текущего задания */
double integral; /* значение интеграла */
double total; /* итоговое значение */
int source; /* отправитель сообщения */
int dest = 0; /* получатель (корневой проц.)*/
int tag = 0;
MPI_Status status;
void Get_data(double* a_ptr, double* b_ptr,
int* n_ptr, int my_rank, int p);
double Trap(double local_a, double local_b, int local_n,
double h); /* вычисление значения на участке */
/* Входим в коммуникатор MPI */
MPI_Init(&argc, &argv);
/* Узнаем свой порядковый номер */
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
/* Узнаем количество выполняющихся заданий */
MPI_Comm_size(MPI_COMM_WORLD, &p);
Get_data(&a, &b, &n, my_rank, p);
h = (b-a)/n; /* h вычисляем интервал разбиения */
local_n = n/p; /* и количество интервалов */
/* Подынтервал интегрирования для каждого задания
равен local_n*h. Локальные пределы интегрирования:
*/
local_a = a + my_rank*local_n*h;
local_b = local_a + local_n*h;
integral = Trap(local_a, local_b, local_n, h);
/* Добавляем вклады от каждого из заданий */
if (my_rank == 0) {
total = integral;
for (source = 1; source < p; source++) {
MPI_Recv(&integral, 1, MPI_double, source, tag,
MPI_COMM_WORLD, &status);
total = total + integral;
}
} else {
MPI_Send(&integral, 1, MPI_double, dest,
tag, MPI_COMM_WORLD);
}
/* Вывод результата */
if (my_rank == 0) {
printf("n = %d интервалов\n", n);
printf("интеграл от %lf до %lf = %lf\n",
a, b, total);
}
/* Завершаем работу MPI */
void Get_data(
double* a_ptr /* out */,
double* b_ptr /* out */,
int* n_ptr /* out */,
int my_rank /* in */,
int p /* in */) {
int source = 0; /* Переменные для функций */
int dest; /* MPI_Send и MPI_Recv */
int tag;
MPI_Status status;
if (my_rank == 0){
printf("Введите a, b, и n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
for (dest = 1; dest < p; dest++){
tag = 0;
MPI_Send(a_ptr, 1, MPI_double, dest, tag, MPI_COMM_WORLD);
tag = 1;
MPI_Send(b_ptr, 1, MPI_double, dest, tag, MPI_COMM_WORLD);
tag = 2;
MPI_Send(n_ptr, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
}
} else {
tag = 0;
MPI_Recv(a_ptr,1,MPI_double, source, tag, MPI_COMM_WORLD
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.