
ОП5
.docxГУАП
КАФЕДРА ВЫЧИСЛИТЕЛЬНЫХ СИСТЕМ И СЕТЕЙ
ОТЧЕТ ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
Ассистент |
|
|
|
Рыжов К.Ю. |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №5 |
ПАРАЛЛЕЛИЗМ |
по курсу: ОСНОВЫ ПРОГРАММИРОВАНИЯ |
|
РАБОТУ ВЫПОЛНИЛ
СТУДЕНТ ГР. № |
4116 |
|
|
|
|
|
|
|
подпись, дата |
|
инициалы, фамилия |
Санкт-Петербург 2022
Цель лабораторной работы: изучение автоматического распараллеливания кода, использующего стандартные алгоритмы библиотеки STL, способов применения и особенностей работы; получение навыков программирования на языке C++.
Задание на программирование: разработать программу и провести анализ эффективности работы с использованием различных политик распараллеливания и с использованием автоматического параллелизатора, автоматического векторизатора.
Вариант 23:
Подсчитать количество элементов коллекции L , которые совпадают с последним элементом.
Описание модели решения: для решения поставленной задачи был взят код из предыдущей лабораторной работы. Чтобы были доступны политики параллельного исполнения, подключена библиотека execution. Политики использовались в методах count и generate. Для работы с потоками подключена библиотека thread. Встроенная функция thread::hardware_concurrency возвращает количество одновременных потоков.
Исходный код:
#include <iostream>
#include <vector>
#include<algorithm>
#include <thread>
#include <ctime>
#include <execution>
using namespace std;
int random()
{
return rand() % 6;
}
template<class Type> void count(vector<Type> arr)
{
cout << endl << count(execution::par_unseq,arr.begin(), arr.end(), arr.back()) - 1 << " elements matching the last" << endl;
}
template<class Type> void fill(vector<Type>& arr, int n)
{
arr.resize(n);
generate(execution::par_unseq, arr.begin(), arr.end(), random);
}
template<class Type> void print(Type& arr)
{
for (auto x : arr)
cout << x << " ";
cout << endl;
}
int main()
{
unsigned int k = std::thread::hardware_concurrency();
cout << "Thread number: " << k << endl;
srand(time(0));
CLOCKS_PER_SEC;
int n;
cout << "Enter capacity of conteiners: ";
cin >> n;
cout << endl;
clock_t start = clock();
cout << "Vector: ";
clock_t start1 = clock();
vector<int> v;
fill(v, n);
count(v);
clock_t end1 = clock();
cout << "Time: " << (end1 - start1) / 1000.0 << endl;
//print(v);
}
Проверка работоспособности алгоритма:
Код без оптимизации и использования политик:
Политика «PAR
-Без
оптимизации кода
-Оптимизация
О1(автоматическая параллелизация).
-Оптимизация
О2(автоматическая векторизация).
Вывод: parallel_policy (execution::par) замедлила выполнение вектора в сравнении с кодом без политик. Автоматическая параллелизация и векторизация немного ускорили выполнение, однако время осталось примерно в тех же пределах.
Политика «SEQ»
-Без
оптимизации кода
-Оптимизация
О1(автоматическая параллелизация).
-Оптимизация
О2(автоматическая векторизация).
Вывод: sequenced_policy (execution::seq) замедлила выполнение вектора без оптимизации кода, автоматическая параллелизация никак не повлиял, а вот векторизация уменьшила время выполнения.
Политика «PAR_UNSEQ»
-Без
оптимизации кода.
-Оптимизация
О1(автоматическая параллелизация).
-Оптимизация
О2 (автоматическая векторизация).
Вывод: parallel_unsequenced_policy (execution::par_unseq) никак не повлияла на время выполнения вектора в сравнении с кодом без политик и без оптимизации. Автоматическая векторизация и параллелизация ускорили выполнение.
Таблица сравнения результатов
Политика\Оптимизация |
Без оптимизации |
Автоматическая параллелизация
|
Автоматическая векторизация |
Par |
0.067 |
0.062 |
0.063 |
Seq |
0.069 |
0.064 |
0.062 |
Par_unseq |
0.064 |
0.056 |
0.059 |
Вывод: были использованы все методы оптимизации кода , самая подходящая комбинация – автоматическая параллелизация и политика par_unseq. Иным задачам, для получения максимального быстродействия может подойти другая комбинация настроек компилятора и политки.