Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лаб. 6 ТПП

.docx
Скачиваний:
1
Добавлен:
29.12.2024
Размер:
270.76 Кб
Скачать

Лабораторная работа №6

Замки и барьеры

Цель: изучить основные особенности использования барьеров и замков в OpenMP на примере использования в рамках языка С++.

Пример:

Задание 1:

#include <iostream>

#include <omp.h>

#include <iomanip>

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;

double start_time = omp_get_wtime();

long total = 0;

omp_lock_t lock;

omp_init_lock(&lock); // Инициализация семафора

#pragma omp parallel num_threads(3) shared(a, b, c, total, lock)

{

#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];

// Использование семафора для обновления общей переменной

omp_set_lock(&lock);

total += c[i];

omp_unset_lock(&lock);

}

}

omp_destroy_lock(&lock); // Освобождение семафора

double end_time = omp_get_wtime();

//cout << "Задание 1:" << endl;

cout << "Замки" << endl;

cout << "Итоговая сумма: " << total << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time - start_time) << " секунд" << endl;

double start_time_r = omp_get_wtime();

long total_r = 0;

#pragma omp parallel num_threads(3) shared(a,b,c) reduction(+:total_r)

{

#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];

total_r += c[i];

}

}

double end_time_r = omp_get_wtime();

cout << "reduction" << endl;

cout << "Итоговая сумма: " << total_r << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time_r - start_time_r) << " секунд" << endl;

delete[] a;

delete[] b;

delete[] c;

return 0;

}

Тратится время на выполнение операций установки и снятия замка. Если один поток удерживает замок, то другие потоки должны ждать, что тоже занимает время.

#include <iostream>

#include <omp.h>

#include <iomanip>

const int N = 1000;

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;

double start_time = omp_get_wtime();

long total = 0;

#pragma omp parallel num_threads(3) shared(a, b, c) reduction(+:total)

{

#pragma omp for nowait private(i)

for (i = 0; i < N; i++)

{

if (a[i] > b[i])

c[i] = a[i];

else

c[i] = b[i];

//total += c[i];

}

#pragma omp for private(i)

for (i = 0; i < N; i++)

{

total += c[i];

}

}

double end_time = omp_get_wtime();

cout << "Без барьерной синхронизации" << endl;

cout << "Итоговая сумма: " << total << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time - start_time) << " секунд" << endl;

total = 0;

start_time = omp_get_wtime();

#pragma omp parallel num_threads(3) shared(a, b, c) reduction(+:total)

{

int thread_id = omp_get_thread_num();

#pragma omp for nowait private(i)

for (i = 0; i < N; i++)

{

if (a[i] > b[i])

c[i] = a[i];

else

c[i] = b[i];

//total += c[i];

}

#pragma omp barrier

printf("Поток %d дошёл до барьера\n", thread_id);

#pragma omp for private(i)

for (i = 0; i < N; i++)

{

total += c[i];

}

}

end_time = omp_get_wtime();

cout << "С барьерной синхронизацией" << endl;

cout << "Итоговая сумма: " << total << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time - start_time) << " секунд" << endl;

delete[] a;

delete[] b;

delete[] c;

return 0;

}

Директива nowait позволяет избежать барьерной синхронизации после выполнения конструкций: for, sections, single.

#include <iostream>

#include <omp.h>

#include <iomanip>

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;

double start_time = omp_get_wtime();

long total = 0;

#pragma omp parallel num_threads(3) shared(a, b, c) reduction(+:total)

{

#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];

total += c[i];

}

}

double end_time = omp_get_wtime();

cout << "Без барьерной синхронизации" << endl;

cout << "Итоговая сумма: " << total << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time - start_time) << " секунд" << endl;

total = 0;

start_time = omp_get_wtime();

#pragma omp parallel num_threads(3) shared(a, b, c) reduction(+:total)

{

int thread_id = omp_get_thread_num();

#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];

total += c[i];

}

#pragma omp barrier

//#pragma omp single

// {

// cout << "Все потоки завершили вычисления." << endl;

printf("Поток %d дошёл до барьера\n", thread_id);

// }

}

end_time = omp_get_wtime();

cout << "С барьерной синхронизацией" << endl;

cout << "Итоговая сумма: " << total << endl;

cout << "Время выполнения: " << fixed << setprecision(16) << (end_time - start_time) << " секунд" << endl;

delete[] a;

delete[] b;

delete[] c;

return 0;

}

Соседние файлы в предмете Технологии параллельного программирования