МИНИСТЕРСТВО ОБРАЗОВАНИЯ
РЕСПУБЛИКИ БЕЛАРУСЬ
ГОМЕЛЬСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ ИМЕНИ П. О. СУХОГО
Факультет автоматизированных и информационных систем
Кафедра: «Информационные технологии»
ЛАБОРАТОРНАЯ РАБОТА № 9
по дисциплине «Основы мультипрограммной и мультипроцессорной
обработки данных»
Выполнил: студент гр. ИТ-32
Принял: преподаватель
Гомель 2013
ЛАБОРАТОРНАЯ РАБОТА №9
Программирование многопоточных приложений в OC Linux.
Цель работы: разработать программу, осуществляющую решение поставленной задачи с помощью многопоточного приложения
Задание:
Разработать многопоточное приложение вычисляющее параллельно значения заданной функции на отрезке [A; B] и на отрезке [C; D] с шагом ∆x . Все коэффициенты α i , β j , γk и значение функции f (x) вычислять параллельно в отдельных потоках (должно быть не менее 5 параллельных потоков). Результаты вычислений сохранять в текстовые файлы. В первый файл сохранить результаты вычислений функции f (x) на отрезке [A; B]
и все коэффициенты α i , β j , γk , во второй – значения f (x) на отрезке [A; B] на отрезке
[C;D]. Для синхронизации потоков использовать указанные средства синхронизации.
Обеспечить монопольный доступ к файлам каждому из потоков, для этого использовать средства синхронизации.
Листинг программы:
#include <pthread.h>
#include <math.h>
#include <stdio.h>
#include <semaphore.h>
#include <string.h>
using namespace std;
void* MainThread(void* param);
FILE *File1, *File2;
void* Otrezok(void* param);
void Wait(long* t)//ф-ция ожидания
{while(*t==0);}
void TestAndSet(long* t)//ф-ция проверки
{ if(*t==0) *t=1;
else *t=0;
}
typedef struct Dannie //структура данных
{ float a;
float b;
float dx;
double* buffer;
int* i;
float* x;
bool* gotov;
long* sinx;
sem_t* SemViv;
sem_t* SemMain;
FILE* File;
} dan,*dannie;
int main()
{pthread_t MThread1,MThread2;
char buf[100];
double* bufZnach1;
double* bufZnach2;
dannie ab,cd;
sem_t SemViv1,SemMain1,
SemViv2,SemMain2;
ab=new Dannie;
cd=new Dannie;
int i1=0,i2=0;
float zx1=0,zx2=0,a1,b1,a2,b2,dx1,dx2;
bool g1=true,g2=true;
long *s1;
long *s2;
s1=new long[4];s1[0]=1; s1[1]=0;s1[2]=0;s1[3]=0;
s2=new long[4];s2[0]=1; s2[1]=0;s2[2]=0;s2[3]=0;
sem_init(&SemViv1,0,1);
sem_init(&SemMain1,0,1);
sem_init(&SemViv2,0,1);
sem_init(&SemMain2,0,1);
File1=fopen("file1.txt","w");
File2=fopen("file2.txt","w");
puts("Ввод данных для потока 1:");
printf("Введите начальное значение: ");
scanf("%f",&a1);
printf("\nВведите конечное значение: ");
scanf("%f",&b1);
printf("\n Введите шаг: ");
scanf("%f",&dx1);
puts("Ввод данных для потока 2:");
printf("\nВведите начальное значение: ");
scanf("%f",&a2);
printf("\nВведите конечное значение: ");
scanf("%f",&b2);
printf("\nВведите шаг: ");
scanf("%f",&dx2);
ab->a=a1;
ab->b=b1;
ab->dx=dx1;
bufZnach1=new double[5];
ab->buffer=bufZnach1;
ab->i=&i1;
ab->x=&zx1;
ab->gotov=&g1;
ab->sinx=s1;
ab->SemViv=&SemViv1;
ab->SemMain=&SemMain1;
ab->File=File1;
pthread_create(&MThread1,NULL,MainThread,ab);
puts("Поток для вычисления отрезка AB запущен!");
cd->a=a2;
cd->b=b2;
cd->dx=dx2;
bufZnach2=new double[5];
cd->buffer=bufZnach2;
cd->i=&i2;
cd->x=&zx2;
cd->gotov=&g2;
cd->sinx=s2;
cd->SemViv=&SemViv2;
cd->SemMain=&SemMain2;
cd->File=File2;
pthread_create(&MThread2,NULL,MainThread,cd);//ñîçäàíèå ïîòîêà2
puts("Поток для вычисления отрезка CD запущен!");
pthread_join(MThread1,NULL);
pthread_join(MThread2,NULL);
puts("Все потоки завершены! Результаты записаны в файл!");
}
void* Alfa(void* param)//поток для вычисления альфа
{ dannie d=(dannie) param;
int* i=d->i;
float* x=d->x;
double* buffer=d->buffer;
bool* gotov=d->gotov;
while(gotov)
{ Wait(&(d->sinx[0]));
double sum=0;
for(int j=1;j<=*i;j++)
sum=sum+sin(*x);
buffer[0]=sum;
TestAndSet(&(d->sinx[0]));
TestAndSet(&(d->sinx[1]));
}
}
void* Betta(void* param)
{
dannie d=(dannie) param;
int* i=d->i;
float* x=d->x;
double* buffer=d->buffer;
bool* gotov=d->gotov;
while(gotov)
{ Wait(&(d->sinx[1]));
double sum=0;
for(int j=1;j<=*i;j++)
sum=sum+sin(*x)*buffer[0];
buffer[1]=sum;
TestAndSet(&(d->sinx[1]));
TestAndSet(&(d->sinx[2]));
}
}
void* Gamma(void* param)
{ dannie d=(dannie) param;
int* i=d->i;
float* x=d->x;
double* buffer=d->buffer;
bool* gotov=d->gotov;
while(gotov)
{
Wait(&(d->sinx[2]));
double sum=0;
for(int j=1;j<=*i;j++)
sum=sum+1./(*i);
sum=sum*buffer[0];
buffer[3]=sum;
sum=0;
for(int j=1;j<=*i;j++)
sum=sum+sin(*x)*cos(buffer[3]);
buffer[2]=sum;
TestAndSet(&(d->sinx[2]));
TestAndSet(&(d->sinx[3]));
}
}
void* MainThread(void* param)
{ dannie d=(dannie) param;
float a=d->a;
float b=d->b;
float dx=d->dx;
double* buffer=d->buffer;
bool* gotov=d->gotov;
int* i=d->i;
float* x=d->x;
long* sinx=d->sinx;
FILE* file=d->File;
*x=a;
//создаем потоки
pthread_t hThread[3];
pthread_create(&hThread[0],NULL,Alfa,d);
pthread_create(&hThread[1],NULL,Betta,d);
pthread_create(&hThread[2],NULL,Gamma,d);
char bufferToWrite[500];
while(*x<b)
{
double summa=0;
for(*i=0;*i<=1000;*i=*i+1)
{ Wait(&(d->sinx[3]));
summa=summa+(pow((1+*x),buffer[0])+pow((1+*x),buffer[1])+pow((1+*x),buffer[2]));
sem_wait(d->SemViv);
sprintf(bufferToWrite," \r\n\n A%d=%.3f B%d=%.3f G%d=%.3f\r\n\n ",*i,buffer[0],*i,buffer[1],*i,buffer[2]);
fwrite(bufferToWrite,1,strlen(bufferToWrite),file);
sem_post(d->SemViv);
TestAndSet(&(d->sinx[3]));
TestAndSet(&(d->sinx[0]));
}
buffer[4]=summa;
sem_wait(d->SemMain);
sprintf(bufferToWrite," \r\nf(%.3f)=%f\r\n ",*x,buffer[4]);
fwrite(bufferToWrite,1,strlen(bufferToWrite),file);
sem_post(d->SemMain);
*x=*x+dx;
}
*gotov=false;
}
Результаты работы программы:
Вывод:была разработана программа, осуществляющая решение поставленной задачи с помощью многопоточного приложения, реализованная средствами Linux. Данное многопоточное приложение, разработанное в Linux работает быстрее, чем такое же приложение, но разработанное средствами WINAPI и .Net.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.