Считаем интеграл методом левых прямоугольников. Просто и безвкусно.
Вычисления будем проводить на одной машине, потому что у меня их одна.
Главное действующее лицо: Intel(R) Pentium(R) Dual CPU E2200 @ 2.20GHz
OS: Ubuntu 10.04 2.6.32-32-generic x86_64
MPICH2 Version: 1.2.1p1
GCC: 4.4.3-4ubuntu5
/*
MPI вариант численного интегрирования:
/*
Барабанная дробь!
$ time mpirun -l -n 2 ./mpiapp
0: => MPI
1: Start working
0: Number of quantization steps 500M
0: Start working
1: Job is done! [250000000; 500000000) Result = 0.307341
0: Job is done! [0; 250000000) Result = 3.508443
0: Result with MPI: 3.815784
real 0m17.342s
user 0m0.090s
sys 0m0.030s
В общем будем считать, что победила дружба.
Вычисления будем проводить на одной машине, потому что у меня их одна.
Главное действующее лицо: Intel(R) Pentium(R) Dual CPU E2200 @ 2.20GHz
OS: Ubuntu 10.04 2.6.32-32-generic x86_64
MPICH2 Version: 1.2.1p1
GCC: 4.4.3-4ubuntu5
OpenMP вариант численного интегрирования:
/*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) 2011 Brunql
*
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*/
#include <omp.h>
#include <stdio.h>
#include <cmath>
#include <string>
// Integral limits [a;b)
const double a = 0;
const double b = M_PI;
// Number of quantization steps in [a,b)
const int N = (500*1000*1000);
// Quantization step
const double step = (b - a) / N;
// Integral evaluation function
static inline double f(double x)
{return cos(x)*sin(x)*x*x + 2;
}
double evalIntegral()
{double result = 0;
# pragma omp parallel for reduction(+:result) schedule(dynamic,(N/1000))
for(int i = 0; i < N; i++)
{
double x = a + i * step;
result += f(x) * step;
}
return result;
}
int main(int argc, char **argv)
{printf("=> OpenMP\n");
printf("Number of quantization steps %iM\n", N / 1000000);
fflush(stdout);
# pragma omp parallel
{
# pragma omp critical
{
printf("Start working thread #%i of %i\n",
omp_get_thread_num(), omp_get_num_threads());
}
}
// Looooooong call
double result = evalIntegral();
printf("Result with OpenMP: %lf\n", result);
return 0;
}MPI вариант численного интегрирования:
/*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) 2011 Brunql
*
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*/
#include <mpi.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
// Integral limits [a;b)
const double a = 0;
const double b = M_PI;
// Number of quantization steps in [a,b)
const int N = (500*1000*1000);
// Quantization step
const double step = (b - a) / N;
// Integral evaluation function
static inline double f(double x)
{return cos(x)*sin(x)*x*x + 2;
}
double evalIntegral(int start, int end)
{double result = 0;
for (int i = start; i < end; i++)
{
double x = a + i * step;
result += f(x) * step;
}
return result;
}
int main (int argc, char* argv[])
{MPI_Init(&argc, &argv);
int rank;
int sizeOfWorld;
MPI_Status mpiStatus;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &sizeOfWorld);
static const int MasterRank = 0;
if (rank == MasterRank)
{
// Master
printf("=> MPI\n");
printf("Number of quantization steps %iM\n", N / 1000000);
fflush(stdout);
}
printf("Start working\n");
fflush(stdout);
int numOfWorkers = sizeOfWorld;
int start = N / numOfWorkers * rank;
int end = start + N / numOfWorkers;
// Looooooong call
double result = evalIntegral(start, end);
printf("Job is done! [%i; %i) Result = %lf\n", start, end, result);
fflush(stdout);
if (rank != MasterRank)
{
// Workers send results to master
MPI_Send(&result, 1, MPI_DOUBLE, MasterRank, 0, MPI_COMM_WORLD);
}
// Master collect results
if (rank == MasterRank)
{
double resultFromWorker = 0;
for (int id = 1; id < sizeOfWorld; id++)
{
MPI_Recv(&resultFromWorker, 1, MPI_DOUBLE, id,
MPI_ANY_TAG, MPI_COMM_WORLD, &mpiStatus);
result += resultFromWorker;
}
printf("Result with MPI: %lf\n", result);
}
MPI_Finalize();
return 0;
}Барабанная дробь!
$ time ./openmp
=> OpenMP
Number of quantization steps 500M
Start working thread #0 of 2
Start working thread #1 of 2
Result with OpenMP: 3.815784
real 0m17.042s
user 0m33.700s
sys 0m0.020s
$ time mpirun -l -n 2 ./mpiapp
0: => MPI
1: Start working
0: Number of quantization steps 500M
0: Start working
1: Job is done! [250000000; 500000000) Result = 0.307341
0: Job is done! [0; 250000000) Result = 3.508443
0: Result with MPI: 3.815784
real 0m17.342s
user 0m0.090s
sys 0m0.030s
Представленные результаты являются моментальными, то есть никаких усреднений не проводилось. Делать какие-то выводы считаю бессмысленным в виду того, что сравнивать холодное с красным как минимум не логично. Использование MPI на одной машине с одним процессором и парой ядер практически бессмысленно. Единственная вещь, которая оправдывает затраченные усилия, это полученный опыт использования данных инструментов. Что собственно и являлось главной целью данного теста.
Пока писал примеры для сравнения производительности, у меня закралась шальная мысль, а что если их объединить? Смысла судя по тестам скорости не много, но ведь скорость работы это одно, а скорость разработки немного ортогональная вещь, которая очень сильно зависит от используемого инструмента. На OpenMP очень удобно постепенно распараллеливать уже написанный код, и ничуть не менее удобно писать новый. В тоже время MPI обеспечивает достаточно мощный интерфейс для обмена результатами вычислений между различными вычислительными блоками. Конечно на вскидку сложно придумать сферу применения данного подхода.
Пока писал примеры для сравнения производительности, у меня закралась шальная мысль, а что если их объединить? Смысла судя по тестам скорости не много, но ведь скорость работы это одно, а скорость разработки немного ортогональная вещь, которая очень сильно зависит от используемого инструмента. На OpenMP очень удобно постепенно распараллеливать уже написанный код, и ничуть не менее удобно писать новый. В тоже время MPI обеспечивает достаточно мощный интерфейс для обмена результатами вычислений между различными вычислительными блоками. Конечно на вскидку сложно придумать сферу применения данного подхода.
В общем будем считать, что победила дружба.

Комментариев нет:
Отправить комментарий
А у тебя есть клавиатура? Здесь можно попробовать воспользоваться ей по прямому назначению.