Вычисление числа Пи. Мирошник Глеб. 6 курс — различия между версиями
(→Для суммирования ряда) |
(→Результаты) |
||
Строка 168: | Строка 168: | ||
− | ==Результаты== | + | ==Результаты (при 10млн итераций)== |
+ | ===Для суммирования ряда=== | ||
{| class="wikitable" width="300" floating="center" | {| class="wikitable" width="300" floating="center" | ||
!Количество процессов | !Количество процессов | ||
− | !Время | + | !Ошибка вычисления |
+ | !Время расчёта (сек) | ||
|- | |- | ||
|1 | |1 | ||
− | | | + | |33.02161870037517132914 |
+ | |1.757 | ||
|- | |- | ||
|2 | |2 | ||
− | | | + | |0.00000010000398731336 |
+ | |0.979 | ||
|- | |- | ||
− | | | + | |3 |
− | | | + | |10.37762764928963399313 |
+ | |0.750 | ||
|- | |- | ||
− | | | + | |4 |
− | | | + | |0.00000009999904815317 |
+ | |0.727 | ||
+ | |} | ||
+ | ===Для интегрирования=== | ||
+ | {| class="wikitable" width="300" floating="center" | ||
+ | !Количество процессов | ||
+ | !Ошибка вычисления | ||
+ | !Время расчёта (сек) | ||
|- | |- | ||
− | | | + | |1 |
− | | | + | |0.00000000000006217249 |
+ | |0.246 | ||
+ | |- | ||
+ | |2 | ||
+ | |0.00000000000019184654 | ||
+ | |0.144 | ||
|- | |- | ||
− | | | + | |3 |
− | | | + | |0.00000000000011946000 |
+ | |0.128 | ||
|- | |- | ||
− | | | + | |4 |
− | | | + | |0.00000000000010702550 |
+ | |0.112 | ||
|} | |} | ||
Версия 13:58, 19 января 2017
Содержание
Цель
Оценить число π при помощи знакочередующегося ряда Лейбница двумя способами: суммированием и интегрированием. Разработать программу для параллельных вычислений. Оценить скорость вычислений в зависимости от количества задействованных процессоров.
Постановка задачи
Лейбниц доказал, что ряд
равен
- .
Также данный ряд можно получить разложением арктангенса 1 в ряд Тейлора, что даёт нам возможность оценить число π вычислением определённого интеграла
Предлагаемое решение
Суммированием элементов ряда
После объявления переменных и инициализации MPI запускается счётчик времени. Предлагается при фиксированном количестве элементов ряда n считать элементы последовательно каждым процессором, "перепрыгивая" через количество процессов, занятых в расчёте. Начальный рассчитываемый номер ряда определяется порядковым номером процесса. Рассчитанный элемент добавляется к сумме внутри процесса. После окончания расчёта предварительные суммы "скидываются" в нулевой процесс и суммируются между собой. Таймер останавливается. Происходит вычисление ошибки по эталонному значению числа π и вывод информации о расчёте.
Численным вычислением определённого интеграла
Численное вычисление интеграла предлагается проводить методом прямоугольников. Сам же процесс будет аналогичен решению суммированием элементов ряда.
Листинг программ
Для суммирования ряда
#include "stdafx.h"
#include <iostream>
#include "mpi.h"
#include <math.h>
#include <time.h>
using namespace std;
#define Iterations 10000000 //количество итераций
int main() {
int ProcNum, ProcRank, i;
double x, MyPi = 0;
double Sum = 0;
double TotalTime;
clock_t StartClock, EndClock; // объявляем стартовую и конечную переменную таймера и инициализируем стартовую переменную
StartClock = clock();
MPI_Init(NULL, NULL); // инициализируем MPI
MPI_Comm_size(MPI_COMM_WORLD, &ProcNum); // записываем количество процессов с переменную ProcNum
MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank); // записываем номер процесса в переменную ProcRank
for (i = ProcRank; i < Iterations; i += ProcNum)
{
x = pow(-1,ProcRank)*4/(2*i + 1);
Sum += x;
}
MPI_Reduce(&Sum, &MyPi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); // пердварительные суммы Sum в переменную MyPi
MPI_Finalize(); // завершаем работу MPI
if (ProcRank == 0)
{
EndClock = clock(); // останавливаем таймер и переходим к выводу результатов на экран
printf("Number of iterations = %i\n", Iterations);
printf("Obtained value of Pi = %3.20f\n", MyPi);
double pi = 3.1415926535897932384626433832795;
printf("Refrence value of Pi = %3.20f\n", pi);
printf("Error = %3.20f\n", abs(MyPi - pi));
TotalTime = (double)(EndClock - StartClock) / CLOCKS_PER_SEC;
printf("Computing time = %f sec\n", TotalTime);
} }
Для вычисления интеграла
#include "stdafx.h"
#include <iostream>
#include "mpi.h"
#include <math.h>
#include <time.h>
using namespace std;
#define Iterations 10000000 //количество итераций
int main() {
int ProcNum, ProcRank, i;
double x, MyPi = 0;
double Sum = 0;
double TotalTime;
clock_t StartClock, EndClock; // объявляем стартовую и конечную переменную таймера и инициализируем стартовую переменную
StartClock = clock();
MPI_Init(NULL, NULL); // инициализируем MPI
MPI_Comm_size(MPI_COMM_WORLD, &ProcNum); // записываем количество процессов с переменную ProcNum
MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank); // записываем номер процесса в переменную ProcRank
double h = 1.0 / Iterations;
for (i = ProcRank; i < Iterations; i += ProcNum) // вычисляем численно интеграл по методу прямоугольников
{
x = (i + 0.5) * h;
Sum += 4.0 / (1 + x*x); // (после общего суммирования надо будет разделить на количество итераций)
}
MPI_Reduce(&Sum, &MyPi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); // пердварительные суммы Sum в переменную MyPi
MPI_Finalize(); // завершаем работу MPI
if (ProcRank == 0)
{
MyPi *= h; //делим сумму на количество итераций
EndClock = clock(); // останавливаем таймер и переходим к выводу результатов на экран
printf("Number of iterations = %i\n", Iterations);
printf("Obtained value of Pi = %3.20f\n", MyPi);
double pi = 3.1415926535897932384626433832795;
printf("Refrence value of Pi = %3.20f\n", pi);
printf("Error = %3.20f\n", abs(MyPi - pi));
TotalTime = (double)(EndClock - StartClock) / CLOCKS_PER_SEC;
printf("Computing time = %f sec\n", TotalTime);
} }
Компьютерная реализация
Результаты (при 10млн итераций)
Для суммирования ряда
Количество процессов | Ошибка вычисления | Время расчёта (сек) |
---|---|---|
1 | 33.02161870037517132914 | 1.757 |
2 | 0.00000010000398731336 | 0.979 |
3 | 10.37762764928963399313 | 0.750 |
4 | 0.00000009999904815317 | 0.727 |
Для интегрирования
Количество процессов | Ошибка вычисления | Время расчёта (сек) |
---|---|---|
1 | 0.00000000000006217249 | 0.246 |
2 | 0.00000000000019184654 | 0.144 |
3 | 0.00000000000011946000 | 0.128 |
4 | 0.00000000000010702550 | 0.112 |
Выводы
- Для малого числа узлов в сетке использовать многопроцессорные вычисления не выгодно: время работы программы увеличивается.
- При увеличении числа процессоров относительный выигрыш во времени уменьшается.