Вы находитесь на странице: 1из 7

МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ

ФЕДЕРАЦИИ

ФГБОУ ВО «НОВОСИБИРСКИЙ ГОСУДАРСТВЕННЫЙ


ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет автоматики и вычислительной техники

Кафедра АСУ

ОТЧЕТ

по лабораторной работе №1

Дисциплина «Параллельное программирование»

Факультет: АВТФ Преподаватель: Ландовский

Группа: АВТ-114 Владимир Владимирович

Студенты:

Белов А.С.

Плотников В.В.
Новосибирск 2023

Задание
Реализовать заданный метод численного интегрирования на языке С++ с
использованием стандарта POSIX (функций pthread_create, pthread_join).

Входные параметры: пределы интегрирования, количество потоков (от 1 до


8), величина шага или количество шагов.

Выходная информация: значение интеграла, время, затраченное на


вычисления.

Подынтегральная функция выбирается самостоятельно.

Варианты метода: метод трапеций.


Схема алгоритма (диаграмма деятельности)
Текст программы

#include <iostream>
#include "pthread.h"
#include <cstdlib>
#include <cmath>
#pragma comment(lib,"pthreadVCE2.lib")

const double a = -4.0;


const double b = 4.0;
const int n = 10000000;
// Глобальная сумма
double s = 0.0;
pthread_mutex_t mutex_sum = PTHREAD_MUTEX_INITIALIZER;

void* integrate(void* arg);

double func(double x) {
return exp(-x * x);
}

struct thread_data {
pthread_t tid;
int threadno;
int nthreads;
};

int main(int argc, char** argv) {


int nthreads = 2;
printf("Numerical integration (%d threads): [%f, %f], n = %d\n", nthreads, a, b, n);
struct thread_data* tdata = (struct thread_data*)malloc(sizeof(struct thread_data) * nthreads);
if (tdata == NULL) {
fprintf(stderr, "Not enough memory\n");
exit(EXIT_FAILURE);
}
for (int i = 1; i < nthreads; i++) {
tdata[i].threadno = i;
tdata[i].nthreads = nthreads;
if (pthread_create(&tdata[i].tid, NULL, integrate, &tdata[i]) != 0) {
fprintf(stderr, "Can't create thread\n");
exit(EXIT_FAILURE);
}
}
tdata[0].threadno = 0;
tdata[0].nthreads = nthreads;
unsigned int start_time = clock();
integrate(&tdata[0]);
for (int i = 1; i < nthreads; i++)
pthread_join(tdata[i].tid, NULL);
free(tdata);
unsigned int end_time = clock();
printf("Result Pi: %.12f\n", s * s);
unsigned int search_time = end_time - start_time;
printf_s("Time: %.6f\n", (double)search_time / 1000);
return 0;
}

void* integrate(void* arg)


{
struct thread_data* p = (struct thread_data*)arg;
double h = (b - a) / n;
int points_per_proc = n / p->nthreads;
int lb = p->threadno * points_per_proc;
int ub = (p->threadno == p->nthreads - 1) ? (n - 1) : (lb + points_per_proc - 1);
double locs = 0.0;
for (int i = lb; i < ub; i++)
locs += func(a + h * (i + 0.5));

locs *= h;
pthread_mutex_lock(&mutex_sum);
s += locs;
pthread_mutex_unlock(&mutex_sum);
return NULL;
}

Примеры работы программы


Результаты экспериментов

Подынтегральная функция Пределы Шаг


f(x) = exp(-x*x) -4 10000000
4
Количество потоков Время, сек. Ответ
1 0,654 3.141589
2 0,255 3.141589
3 0,201 3.141589
4 0,193 3.141589
5 0,185 3.141589
6 0,175 3.141589
7 0,166 3.141589
8 0,165 3.141589
Выводы
Так как каждый поток вычисляет сумму своего отрезка независимо от
других потоков, при этом сам отрезок для одного потока уменьшается с
увеличением количества потоков, то время, затраченное на расчет, должно
уменьшиться, а итоговое значение интеграла не меняться, что и видно из
таблицы и графика результатов эксперимента.

Вам также может понравиться