Суперкомпьютер - это устройство, сводящее проблемы вычислений к проблемам ввода-вывода.
Ken Batcher, 2001
Постоянные читатели (вас нет? ну и ладно) заметили, что последнее время нередко публикуются статьи по теме. Не будем отходить от этой замечательной традиции.
OpenMP
Open Multi-Processing -- удобный и достаточно простой в применении стандарт распараллеливания программ для языков C, C++, Fortran.
Команды OpenMP описываются в C/С++ с использованием префиксов #pragma omp, которые являются простыми директивами препроцессора, и обрабатываются перед непосредственной компиляцией. Препроцессор, поддерживающий OpenMP, обрабатывает их вставляя зависимые от ОС системные вызовы для создания потоков и работы с ними. OpenMP безумно удобен, например если компилятор не поддерживает OpenMP, то он просто проигнорирует все #pragma и код будет выполнен в одном потоке, в результате код получается в достаточной степени переносимым.
В Visual Studio поддержка OpenMP включается соответствующим тумблером в настройках C/C++ / Language, которая передает компилятору параметр /openmp.
Например, при использовании qmake (или QtCreator), в *.pro файле достаточно добавить пару строк:
QMAKE_LIBS += -lgomp
QMAKE_CXXFLAGS += -fopenmp
Пример работы с OpenMP
Вычисление интеграла sin(x) на интервале [0; pi] простейшим методом левых прямоугольников:
/** 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>
const double a = 0, b = M_PI; // integral limits
const int N = 50*1000*1000; // number of quantization steps in [a,b)
const double step = (b - a) / N; // quantization step
// OpenMP Time Evaluations
double g_startTime, g_endTime;
static inline void tStart()
{g_startTime = omp_get_wtime();
}
static inline void tElapsed(std::string str)
{g_endTime = omp_get_wtime();
printf("Time elapsed (%s): %0.4lfs\n", str.c_str(),
g_endTime - g_startTime);
}
// Integral evaluation function
double f(double x)
{return sin(x);
}
double evalIntegralWithoutOpenMP()
{double result = 0;
tStart();
for (int i = 0; i < N; i++)
{
double x = a + i * step;
result += f(x) * step;
}
tElapsed("Without OpenMP");
return result;
}
double evalIntegralOpenMP()
{double result = 0;
tStart();
# 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;
}
tElapsed("With OpenMP");
return result;
}
int main(int argc, char **argv)
{# pragma omp parallel
{
# pragma omp critical
{
printf("Thread #%i of %i\n",
omp_get_thread_num(),
omp_get_num_threads());
}
}
double resultWithoutOpenMP = evalIntegralWithoutOpenMP();
double resultOpenMP = evalIntegralOpenMP();
printf("Result without OpenMP: %lf\n", resultWithoutOpenMP);
printf("Result with OpenMP: %lf\n", resultOpenMP);
return 0;
}При запуске программы получим:
Thread #1 of 2Thread #0 of 2Time elapsed (Without OpenMP): 2.3659sTime elapsed (With OpenMP): 1.1919sResult without OpenMP: 2.000000Result with OpenMP: 2.000000
Судя по выхлопу программы можно понять, что OpenMP определил оптимальное количество потоков равное количеству физических ядер в моей машине, т.е. создал 2 потока. Так же по времени вычисления видно, что скорость параллельного вычисления как раз в два раза выше.
Код с использованием OpenMP отличается от последовательного кода всего лишь одной строчкой. Супер.
Бесполезные ссылки:
1) 32 подводных камня OpenMP при программировании на Си++ (http://www.dtf.ru/articles/read.php?id=55038&page=1)
2) Куча статей по распараллеливанию программ (http://www.viva64.com/ru/r/tag/parallel-programming/)
2) Куча статей по распараллеливанию программ (http://www.viva64.com/ru/r/tag/parallel-programming/)
3) Да ну их, все равно никто по ним не ходит.
Ну вроде, что-то где-то даже получается.
ОтветитьУдалитьОсталось только за завтрашний день MPI осилить и будет очень супер.