Аватар пользователя Administrator

параллельное программирование C++

Разработать программу, загружающую два параллельно работающих процесса, выводящих в свои окна указанные графические данные

Задание

Задание1: Параллельные процессы
Разработать программу, загружающую два параллельно работающих
процесса, выводящих в свои окна указанные графические данные

Окружность и прямоугольник

Область вывода состоит из двух окон: верхнего и нижнего в нечетных
вариантах или левого и правого в четных вариантах. Каждый процесс выводит в свое окно фигуры заданного вида, у которых случайно изменяются цвет,
размеры и положение.

Задание 2: Распараллеливание рекурсивных подпрограмм

Разработать программу, решающую данную задачу с помощью
рекурсивной функции. Преобразовать эту функцию и главную программу в много потоковуюпрограмму. Потоковые функции выполняются со случайной задержкой.

Вариант 1: Вычисление значений многочлена
sin(x)\approx\sum_k^n \frac{(-1)^{k}x^{2k+1}}{(2k+1)!}
по схеме
Горнера методом сдваивания.

1.1 Параллельные процессы


Исходный код программы:
Первый процесс:

#include <windows.h>	//заголовочный файл для win32 приложений
#pragma hdrstop
#define SizeWindow 400	//размер окна

MSG msg;		//сообщение
HDC hdc;		//контекст устройства
HBRUSH hBrush;		//тип кисти
HWND Wnd;		//handle окна
WNDCLASS wnds;		//структура класса окна
char ClassName[255]="Rectangle";	//имя класса окна

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){//оконная функция
switch(uMsg) //обработчик сообщений
{ 		
	case WM_DESTROY:		//выход
		PostQuitMessage(0); return 0;
	case WM_TIMER:		//сработал таймер и нарисовали произвольный четырёхугольник
		Rectangle(hdc, rand() %SizeWindow, rand()%SizeWindow/2, rand()%SizeWindow, rand()%SizeWindow); //нарисовали произвольный четырёхугольник
	default:			//по умолчанию 
		DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
}
}

int WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){
//регистрация класса окна в системе
	wnds.style		=CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS;
	wnds.lpfnWndProc	=WindowProc;
	wnds.cbClsExtra	=0;
	wnds.cbWndExtra	=0;
	wnds.hInstance	=hInstance;
	wnds.hIcon		=LoadIcon(0, IDI_APPLICATION);
	wnds.hCursor	=LoadCursor(0, IDC_ARROW);
	wnds.hbrBackground=(HBRUSH) 6;
	wnds.lpszMenuName	=0;
	wnds.lpszClassName=ClassName;	//атрибуты структуры окна заполнены
	RegisterClass(&wnds); 		//зарегистрируем класс окна
	Wnd=CreateWindowEx(0, ClassName,
		"Процесс1: Прямоугольники",
		WS_EX_DLGMODALFRAME,
		GetSystemMetrics(SM_CXFULLSCREEN)/2 - SizeWindow,
		GetSystemMetrics(SM_CXFULLSCREEN)/2 - SizeWindow,
		SizeWindow, SizeWindow/2,
		0,0,hInstance,0);	//создадим экземпляр  зарегистрированного класса окна
	
	ShowWindow(Wnd,SW_SHOWNORMAL);	//отобразим окно на экране
	hdc=GetDC(Wnd);			//получим его контекст
	SetTimer(Wnd,1,100,NULL);		//установим таймер
	int Exit=1;

	while(Exit)
	{			//обработка сообщений от окна
		if((Exit=GetMessage(&msg,0,0,0)) )
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return 0;
}


Второй процесс

#include <windows.h>	//заголовочный файл для win32 приложений
#pragma hdrstop
#define SizeWindow 400	//размер окна

MSG msg;		//сообщение
HDC hdc;		//контекст устройства
HBRUSH hBrush;		//тип кисти
HWND Wnd;		//handle окна
WNDCLASS wnds;		//структура класса окна
char ClassName[255]="Circle";	//имя класса окна

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){//оконная функция
int x,y,r; //координаты центра и радиус окружности
switch(uMsg)
{
	case WM_DESTROY: 	//выход
		PostQuitMessage(0); return 0;
	case WM_TIMER: 	//таймер
		//генерируем координаты и радиус и рисуем эллипс
		x = rand()%SizeWindow;	y = rand()%SizeWindow;	r = rand()%SizeWindow/4;
		Ellipse(hdc,x-r, y+r,x+r,y-r);
	default: //по умолчанию
		DefWindowProc(hWnd,uMsg,wParam,lParam);
		break;
}
}

int WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int){
//регистрация класса окна в системе
	wnds.style		=CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS;
	wnds.lpfnWndProc	=WindowProc;
	wnds.cbClsExtra	=0;
	wnds.cbWndExtra	=0;
	wnds.hInstance	=hInstance;
	wnds.hIcon		=LoadIcon(0, IDI_APPLICATION);
	wnds.hCursor	=LoadCursor(0, IDC_ARROW);
	wnds.hbrBackground=(HBRUSH) 6;
	wnds.lpszMenuName	=0;
	wnds.lpszClassName=ClassName;	//атрибуты структуры окна заполнены
	RegisterClass(&wnds); 		//зарегистрируем класс окна
	Wnd=CreateWindowEx(0, ClassName,"Процесс2:Окружности",
		WS_EX_DLGMODALFRAME,
		GetSystemMetrics(SM_CXFULLSCREEN)/2-SizeWindow,GetSystemMetrics(SM_CXFULLSCREEN)/2 - 1.75*SizeWindow,
		SizeWindow, SizeWindow/2,0,0,hInstance,0);			//создадим экземпляр зарегистрированного класса
		
	ShowWindow(Wnd,SW_SHOWNORMAL);	//отобразим окно на экране
	hdc=GetDC(Wnd);			//получим его контекст
	SetTimer(Wnd,1,100,NULL); 	//установим для него таймер
	int Exit=1;
	while(Exit)				//обработка сообщений от окна
	{
		if((Exit=GetMessage(&msg,0,0,0)) )
		{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
		}
	}
	return 0;
}



Основной процесс

#include <windows.h>	//заголовочный файл для win32 приложений
#include <string.h>		//заголовочный файл для работы со строками
#include <stdio.h>		//заголовочный файл для ввода-вывода
//идентификаторы, используемые в программе
#define ID_PROCESS 3         
#define ID_KILLPROC 2
#define ID_EXIT 4
#define ID_HELP 1
#define PROCMAX 2
#define MAINMENU 1
#define IDI_ICON1 1
//прототип оконной функции
LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

char szWinName[] = "main"; 	//имя окна
char str[255];		  	//буфер	
int maxX,maxY;			//максимальные значения Х и У
int X=0, Y=0;
int procnum = 0;			//номер процесса

HDC memdc;				//контекст окна
HBITMAP hbit;				//handle картинки
HBRUSH hbrush;			//тип кисти
PROCESS_INFORMATION pinfo[PROCMAX]; 	//массив структур информации 
							//о процессах
//главная функция приложения
int WINAPI WinMain( HINSTANCE hThisInst, HINSTANCE hPrevinst, LPSTR lpszArgs, int nWinMode)
{
	 HWND hwnd;		//handle окна
	 MSG msg;		//сообщение
	 WNDCLASS wcl; 	//класс окна
	 HANDLE hAccel=NULL;	//акселераторы

	//регистрируем новый класс окна в системе
	 wcl.hInstance		 = hThisInst;
	 wcl.lpszClassName 		 = szWinName;
	 wcl.lpfnWndProc	 	 = WindowFunc;
	 wcl.style 			 = 0;
	 wcl.hIcon 		 	 =LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON1));
	 wcl.hCursor		 	 = LoadCursor(NULL,IDC_ARROW);
	 wcl.lpszMenuName	 	 = (LPSTR)MAKEINTRESOURCE(MAINMENU);
	 wcl.cbClsExtra	 	 = 0;
	 wcl.cbWndExtra	 	 = 0;
	 wcl.hbrBackground 		 = (HBRUSH)GetStockObject(WHITE_BRUSH);

	 if(!RegisterClass(&wcl)) return 0; //класс окна зарегистрирован
	//создадим экземпляр нового класса
	hwnd = CreateWindow(szWinName,
		"Лабораторная работа №1, Вариант 1, ПП",
		WS_OVERLAPPEDWINDOW,GetSystemMetrics(SM_CXFULLSCREEN)/2-400,GetSystemMetrics(SM_CXFULLSCREEN)/2-200,450,150,//150,370,450,150, 
		HWND_DESKTOP, NULL, hThisInst, NULL);

	ShowWindow(hwnd,nWinMode);	UpdateWindow(hwnd); //отобразим его на экране

	while(GetMessage(&msg,NULL,0,0)) //обработка сообщений от окна
	{
		if(!TranslateAccelerator(hwnd,(HACCEL)hAccel,&msg))
		{
			TranslateMessage(&msg);	DispatchMessage(&msg);
		}
	 }
	return msg.wParam;
}

//оконная функция
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message,	WPARAM wParam,	LPARAM lParam)
{
	HDC hdc;			//контекст
	PAINTSTRUCT paintstruct;	//структура для рисования
	TEXTMETRIC tm;		
	STARTUPINFO startin;	//структура для запуска процессов

	switch(message)
	{
		case WM_CREATE: //если окно создаётся, заполним область вывода белым цветом
			maxX = GetSystemMetrics(SM_CXSCREEN);
			maxY = GetSystemMetrics(SM_CYSCREEN);
			hdc = GetDC(hwnd);
			memdc = CreateCompatibleDC(hdc);
			hbit = CreateCompatibleBitmap(hdc,maxX,maxY);
			SelectObject(memdc,hbit);
			hbrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
			SelectObject(memdc,hbrush);
			PatBlt(memdc,0,0,maxX,maxY,PATCOPY);
			ReleaseDC(hwnd,hdc);
			break;
		case WM_COMMAND: //если нажата одна из опций меню
			switch (LOWORD (wParam))
			{
				case ID_PROCESS: //открыть процесс
				{	
					if(procnum==PROCMAX) //если их два, то больше нельзя
					{
						MessageBox(hwnd,"Запущены оба процесса", "Ошибка", MB_OK);
						break;
					};
					
					char TestName[]="PP_lab1_process .exe"; //здесь создаётся имя для запуска
					TestName[15]=procnum+49;
					//заполним структуру STARTUPINFO
					startin.cb          = sizeof(STARTUPINFO);
					startin.lpReserved  = NULL;
					startin.lpDesktop   = NULL;
					startin.lpTitle     = NULL;
					startin.dwFlags     = STARTF_USESHOWWINDOW;
					startin.cbReserved2 = 0;
					startin.lpReserved2 = NULL;
					startin.wShowWindow = SW_SHOWNORMAL;
					//запускаем новый процесс
					if (CreateProcess(NULL, TestName ,NULL,NULL,FALSE,0,
						NULL,NULL,&startin, &(pinfo[procnum])))
             	  	{ 	  
						//вывод в главное окно, что процесс создан
						GetTextMetrics(memdc,&tm);
						sprintf(str,"Процесс %d создан",procnum);
						TextOut(memdc,X,Y,str,strlen(str));
						Y = Y + tm.tmHeight+tm.tmExternalLeading;
						InvalidateRect(hwnd,NULL,1);
						//перерисуем окно
						procnum++;
                 	} 
					else MessageBox(hwnd,"Не найдена тестовая программа!","Ошибка",MB_OK);
				
				} 
				break;

				case ID_KILLPROC: //закрыть процесс
					if(procnum) procnum--; //декремент количества процессов
					else
					{ //если нечего закрывать
						MessageBox(hwnd,"Все процессы закрыты","Ошибка",MB_OK);
						break;	
					}
					GetTextMetrics(memdc,&tm);
					//функция завершает процесс
					TerminateProcess(pinfo[procnum].hProcess,0);
					//вывод в главное окно, что процесс завершён
					sprintf(str,"Процесс %d завершен",procnum);
					TextOut(memdc,X,Y,str,strlen(str));
					Y = Y+tm.tmHeight+tm.tmExternalLeading;
                  	InvalidateRect(hwnd,NULL,1);
					break;

					case ID_EXIT: //Выход
					{
						TerminateProcess(pinfo[0].hProcess,0);TerminateProcess(pinfo[1].hProcess,0);
						DeleteDC(memdc);	PostQuitMessage(0);
					}
					break;
			} break;
		case WM_PAINT: //перерисовка окна
			hdc = BeginPaint(hwnd,&paintstruct);
			BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);
			EndPaint(hwnd,&paintstruct);
			break;
		case WM_DESTROY: //если нажата кнопка, закрыть
			DeleteDC(memdc);
			PostQuitMessage(0);
			break;
		default: //	по умолчанию
			return DefWindowProc(hwnd,message,wParam,lParam);
	}
	return 0;
}


Результат работы программы:
Изображение

1.2 Распараллеливание рекурсивных подпрограмм


Исходный код программы:

#include <windows.h>
#include <time.h>              // получение первого случайного числа
#include <iostream>          // ввод-вывод
#include <conio.h>             // для включения ожидания ввода клавиши
using namespace std;
     
#define N 10                   // степень многочлена
double x;                      // значение переменной

struct arg                     // структура для передачи параметров
{
	int l, r;                     // нижний и верхний номера 2х2=матрицы
	double p, q;                  // коэффициенты первой строки матрицы
};

double a[2*N+2];                    // коэффициенты многочлена
DWORD WINAPI prod(void* s)     // функция потока
{
		int i, l=((arg *)s) -> l, r=((arg *)s) -> r;
		Sleep(rand()%1000);           // случайная задержка
		if (l == r)
		{
			((arg *)s) -> p = x;    // установка
			((arg *)s) -> q = a[l];  // коэффициентов
		}
		else
		{
			arg *r1 = new arg, *r2 = new arg;
			HANDLE H[2];                                   // дескрипторы потоков
			r1 -> l = l;				r1 -> r = (l + r + 1)/2 - 1; //установка границ
			r2 -> l = (l + r + 1)/2;	r2 -> r = r;
			H[0] = CreateThread(0,0,prod, (void *)r1,0,0); // порождение
			H[1] = CreateThread(0,0,prod, (void *)r2,0,0);  // потоков
			for (i = 0; i < 2; i++)  WaitForSingleObject(H,INFINITE); // ожидание выполнения потоков
			((arg *)s) -> p = (r1 -> p)*(r2 -> p); //p1*p2
			((arg *)s) -> q = (r1 -> p)*(r2 -> q)+(r1 -> q);//p1*q2+q1
			delete r1; delete r2;
		}
		return 1;
}

double fact(double f)
{
	if(f==0||f==1) return(1);
	return(f*fact(f-1));
}

void main()
{
	int i; double w=0, z;
	srand(time(NULL));//Включение генератора с.ч.
	for (i=0; i <=2*N+1; i=i+2) a[i] = 0;  // установка коэффициентов перед x с чётной степенью
	for (i=0; i <=N; i++) a[2*i+1] = pow(-1.0,(i))/fact(2*i+1);  // установка коэффициентов перед x С нечётной степенью
 
	arg t;                        // объявление структуры параметров
	for (x = 1; x <10; x++) //перебор значений х
	{
		t.l = 0; t.r = 2*N+1;       // границы массива матриц
		prod(&t);  // вызов подпрограммы
  		cout <<"x=" << x << " Polynom value = " << t.q<<endl; // вывод
		z = 0;
		for (i = 0; i <= N; i++)                    // цикл для проверки
		//вычисление правой части выражения
		{	z+=pow(-1.0,i)*pow(x,2*i+1)/fact(2*i+1);	}
		cout <<"\tsin(x)=\t\t" <<sin(x)<<"\n\tRight part=\t"<<z<<endl; // вывод значения для проверки
		getch();                             // ожидание нажатия клавиши
	}

}


[I]Результат работы программы:

Изображение

Комментарии 0 2017-06-16 01:34:49 5