Мы изучили фундаментальные элементы, предоставляемые библиотекой шаблонов для параллельных вычислений, используемые для программ, которые применяют несколько процессов. Библиотека PPL эффективна лишь при наличии существенных объемов вычислений, выполняемых на машине с несколькими процессорами, однако такие задачи отнюдь не редкость. Большинство инженерных и научных приложений входят в эту категорию наряду с множеством операций обработки изображения, и вы вполне можете найти крупномасштабные коммерческие задачи обработки данных, которые могут извлечь пользу из использования библиотеки PPL.
Определите функцию, которая вычислит факториал целого числа типа long long с использованием алгоритма parallel_for. (Факториалом целого числа n является произведение всех целых чисел от 1 до n.) Продемонстрируйте, что функция работает с соответствующей функцией main().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <iostream> using std::cout; using std::endl; #include <ppl.h> unsigned long long fakt(size_t n) { long long f(1); Concurrency::combinable<unsigned long long> fs; fs.local()=1LL; Concurrency::parallel_for(static_cast<size_t>(1),n+1, [&fs](size_t i)->void { fs.local()*=i; }); f=fs.combine( [](unsigned long long s1, unsigned long long s2)->unsigned long long { return s1*s2; }); return f; } int main() { cout <<fakt(20)<<endl; return 0; } |
вывод:
[/tip]
[tip]
Упражнение 2
Определите функцию, которая параллельно вычислит сумму квадратов элементов контейнера array<double>, используя алгоритм parallel_invoke. Массив array<double> должен быть передан как аргумент функции. Продемонстрируйте, что функция работает с соответствующей функцией main(), сначала с ограниченным количеством известных значений, а затем с большим количеством произвольных значений.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <iostream> using std::cout; using std::endl; #include <array> using std::array; #include <cstdlib> using std::rand; using std::srand; #include <ctime> using std::time; #include <algorithm> using std::generate; #include <ppl.h> template<class T> double sumArray(T mass) { //вычислить сумму в два процесса для двухядерного процессора Concurrency::combinable<double> sums; Concurrency::parallel_invoke( [&] { for(size_t i=0;i<mass.size();i+=2) sums.local()+=mass[i]; }, [&] { for(size_t i=1;i<mass.size();i+=2) sums.local()+=mass[i]; }); //объединяем локальные суммы в одну. return sums.combine( [](double s1, double s2)->double { return s1+s2; }); } int main() { array<double,6> mass={1,2,3,4,5}; cout <<"sum 1.2 ... 6 = "<<sumArray(mass)<<endl; array<double, 10000> mass1; srand(time(0)); generate(mass1.begin(),mass1.end(), [] { return static_cast<double>(rand()); }); cout <<"sum of 10000 elements = "<<sumArray(mass1)<<endl; return 0; } |
вывод:
[/tip]
[tip]
Упражнение 3
Повторите предыдущее упражнение, но на сей раз используйте для параллельных вычислений объект task_group.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#include <iostream> using std::cout; using std::endl; #include <array> using std::array; #include <cstdlib> using std::rand; using std::srand; #include <ctime> using std::time; #include <algorithm> using std::generate; #include <ppl.h> template<class T> double sumArray(T mass) { //вычислить сумму в два процесса для двухядерного процессора double sum1(0.0),sum2(0.0); Concurrency::task_group task; task.run( [&] { for(size_t i=0;i<mass.size();i+=2) sum1+=mass[i]; }/*, [&] { for(size_t i=1;i<mass.size();i+=2) sums3.local()+=mass[i]; }*/); for(size_t i=1;i<mass.size();i+=2) sum2+=mass[i]; //ждем пока закончится задание в потоке task.wait(); //объединяем локальные суммы в одну. return sum1+sum2; } int main() { array<double,6> mass={1,2,3,4,5}; cout <<"sum 1.2 ... 6 = "<<sumArray(mass)<<endl; array<double, 10000> mass1; srand(time(0)); generate(mass1.begin(),mass1.end(), [] { return static_cast<double>(rand()); }); cout <<"sum of 10000 elements = "<<sumArray(mass1)<<endl; return 0; } |
вывод:
[/tip]