
Лаб. 4 ТПП
.docxЛабораторная работа №4
Критические секции и атомарные операции
Цель: изучить основные особенности использования критических секций и атомарных операций в OpenMP на примере использования в рамках языка С++.
Пример 1. Использование директивы atomiс:
#include <iostream>
#include <omp.h>
const int NMAX = 3;
int main() {
setlocale(LC_ALL, "Rus");
int i, j;
float total = 0;
float sum;
float a[NMAX][NMAX];
for (i = 0; i < NMAX; i++)
for (j = 0; j < NMAX; j++)
a[i][j] = i + j + 1;
#pragma omp parallel shared(total,a) private(i,j,sum)
{
#pragma omp for
for (i = 0; i < NMAX; i++)
{
sum = 0;
for (j = 0; j < NMAX; j++)
sum += a[i][j];
printf("Сумма элементов строки %d равна %f\n", i, sum);
#pragma omp atomic
total += sum;
}
} /* Завершение параллельного фрагмента */
printf("Сумма элементов матрицы равна %f\n", total);
}
Пример 2. Использование критических секций:
#include <iostream>
#include <omp.h>
const int NMAX = 3;
int main() {
setlocale(LC_ALL, "Rus");
int i, j;
float smax = 0;
float sum;
float a[NMAX][NMAX];
for (i = 0; i < NMAX; i++)
for (j = 0; j < NMAX; j++)
a[i][j] = i + j + 1;
#pragma omp parallel shared(smax,a) private(i,j,sum)
{
#pragma omp for
for (i = 0; i < NMAX; i++)
{
sum = 0;
for (j = 0; j < NMAX; j++)
sum += a[i][j];
printf("Сумма элементов строки %d равна %f\n", i, sum);
//if (sum > smax)
#pragma omp critical
if (sum > smax)
smax = sum;
}
} /* Завершение параллельного фрагмента */
printf("Максимальная сумма равна %f\n", smax);
}
Задание:
#include <iostream>
#include <omp.h>
#include <iomanip>
#include <cstdlib>
const int N = 100;
using namespace std;
int main() {
setlocale(LC_ALL, "Rus");
cout << "N: " << N << endl << endl;
int i;
int* a = new int[N];
int* b = new int[N];
int* c = new int[N];
srand(static_cast<unsigned int>(time(nullptr)));
for (i = 0; i < N; i++)
a[i] = rand() % 21 - 10;
for (i = 0; i < N; i++)
b[i] = rand() % 21 - 10;
// Использование atomic
double start_time_atomic = omp_get_wtime();
long total_atomic = 0;
#pragma omp parallel num_threads(3) shared(a, b, c)
{
#pragma omp for private(i)
for (i = 0; i < N; i++) {
if (a[i] > b[i])
c[i] = a[i];
else
c[i] = b[i];
#pragma omp atomic
total_atomic += c[i];
}
}
double end_time_atomic = omp_get_wtime();
cout << "atomic" << endl;
cout << "Итоговая сумма: " << total_atomic << endl;
cout << "Время выполнения: " << fixed << setprecision(16) << (end_time_atomic - start_time_atomic) << " секунд" << endl;
// Использование critical
double start_time_critical = omp_get_wtime();
long total_critical = 0;
#pragma omp parallel num_threads(3) shared(a, b, c)
{
#pragma omp for private(i)
for (i = 0; i < N; i++) {
if (a[i] > b[i])
c[i] = a[i];
else
c[i] = b[i];
#pragma omp critical
total_critical += c[i];
}
}
double end_time_critical = omp_get_wtime();
cout << "critical" << endl;
cout << "Итоговая сумма: " << total_critical << endl;
cout << "Время выполнения: " << fixed << setprecision(16) << (end_time_critical - start_time_critical) << " секунд" << endl;
delete[] a;
delete[] b;
delete[] c;
return 0;
}