Вычисление числа Пи. Мирошник Глеб. 6 курс — различия между версиями
(→Выводы) |
|||
(не показаны 3 промежуточные версии этого же участника) | |||
Строка 9: | Строка 9: | ||
:<math>\frac{\pi}{4}</math>. | :<math>\frac{\pi}{4}</math>. | ||
Также данный ряд можно получить разложением арктангенса 1 в ряд Тейлора, что даёт нам возможность оценить число π вычислением определённого интеграла | Также данный ряд можно получить разложением арктангенса 1 в ряд Тейлора, что даёт нам возможность оценить число π вычислением определённого интеграла | ||
− | :<math>\int\limits_0^1 \frac{1}{1+x^{2}}\,dx = frac{\pi}{4}</math> | + | :<math>\int\limits_0^1 \frac{1}{1+x^{2}}\,dx = \frac{\pi}{4}</math> |
− | |||
==Предлагаемое решение== | ==Предлагаемое решение== | ||
Строка 166: | Строка 165: | ||
==Компьютерная реализация== | ==Компьютерная реализация== | ||
− | + | [[:File:CompTech.rar|Оценка числа π]] | |
==Результаты (при 10млн итераций)== | ==Результаты (при 10млн итераций)== | ||
Строка 218: | Строка 217: | ||
* Интегрирование при одинаковом количестве итераций даёт более точный результат, а так же результат интегрирующей программы не зависит от количества процессов (при запуске программы с чётным количеством процессов появляется ошибка больше 100%). | * Интегрирование при одинаковом количестве итераций даёт более точный результат, а так же результат интегрирующей программы не зависит от количества процессов (при запуске программы с чётным количеством процессов появляется ошибка больше 100%). | ||
* Ошибка вычисления при интегрировании связана с ограниченным количеством символов типа double; ошибка вычисления при суммировании может быть уменьшена увеличением количества элементов ряда. | * Ошибка вычисления при интегрировании связана с ограниченным количеством символов типа double; ошибка вычисления при суммировании может быть уменьшена увеличением количества элементов ряда. | ||
− | |||
− | |||
− |
Текущая версия на 16:07, 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 |
Выводы[править]
- При увеличении количества процессов сокращается время выполнения программы, но относительный выигрыш по времени уменьшается.
- Интегрирование при одинаковом количестве итераций даёт более точный результат, а так же результат интегрирующей программы не зависит от количества процессов (при запуске программы с чётным количеством процессов появляется ошибка больше 100%).
- Ошибка вычисления при интегрировании связана с ограниченным количеством символов типа double; ошибка вычисления при суммировании может быть уменьшена увеличением количества элементов ряда.