имени А.Г. и Н.Г. Столетовых

Министерство образования и науки РФ

Федеральное государственное бюджетное образовательное учреждение

Высшего профессионального образования

 

Владимирский государственный университет

имени А.Г. и Н.Г. Столетовых

(ВлГУ)

 

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

 

По дисциплине

«Операционные системы»

выполнил:

ст.гр. ВТс-212

Исаков А.В.

принял:

Барков В. А.

 

Владимир 2012г.

1. Текст задания.

1. Составить две многопоточные программы:

1. SinInt.cpp - для приближенного вычисления интеграла от sin(x) в пределах от 0 до Pi методом прямоугольников с разбиением интервала интегрирования на n отрезков (1 млрд.).

2. PrimeCnt.cpp - для опредения количества простых чисел в диапазоне 0..n (100 млн.).

2. Исследовать зависимость времени выполнения программ от числа потоков выполнения.


2. Исходный код программ на языке C++.

// SinInt2.cpp: определяет точку входа для консольного приложения.

 

#include "stdafx.h"

#include <iostream>

#include <Windows.h>

#include <math.h>

using namespace std;

 

void Linear_Calculation(void) ; // функция линейного вычисления

void Parallel_Computation(void); // функция параллельного (потогового) вычисления

double Sum_Element(int) ; // функция суммирования (принимает номер используемого потока)

 

// integral[a, b](sin(x)dx) = sum([a+b]/n * sin[bi])

const double a = 0;

const double b = atan((double)1)*4;

const long int n = 1000000000;

 

int Number_ThReads = 1; // количество потоков

double Resultat = 0; //Результат вычислений

 

DWORD Time_CPU; // Время работы процессора

 

int main()

{

setlocale(LC_ALL, "RUS");

unsigned Num_menu;

 

cout << "Вычисление Интеграла (sin(x)dx) от 0 до Пи\n\n";

cout << "\nВыбирете тип решения\n";

cout << "1. Прямолинейное решение\n";

cout << "2. Использовать параллельные потоки\n";

cout << "3. Выход из програмы \n";

cout << "\nВведите значение: ";

 

cin >> Num_menu;

 

switch(Num_menu) {

case 1: {

Linear_Calculation();

break;

}

case 2: {

Parallel_Computation();

break;

}

default: return 1;

}

system("pause");

return 0;

}

 

 

double Sum_Element(int The_number_of_threads) // функция суммирования (принимает номер используемого потока)

{

long int number_passes = 0;

double Sum_sin= 0;

double h = (a+b)/n;

double i = The_number_of_threads + 1;

while(i<=n)

{

Sum_sin += sin(i * h) * h;

i += Number_ThReads;

number_passes++;

}

cout << "\n Количество вычислений = " << fixed << number_passes << " Использован поток № " << The_number_of_threads;

//fixed по умолчанию отображения чисел с плавающей запятой в экспоненциальном представлении.

return Sum_sin;

}

 

 

void Linear_Calculation() //функция линейного вычисления

{

cout << "\nПроизводятся линейные вычисления, Пожалуйста Подождите ....\n";

Time_CPU= GetTickCount(); // время начала работы процесса

cout.precision(16); //Задает число цифр для отображения числа с плавающей запятой.

Number_ThReads = 1; // количество потоков 1

 

cout << "\n\nРезультат расчета: " << (double)Sum_Element(0) << endl;

 

cout.precision(2); //Задает число цифр для отображения числа с плавающей запятой.

Time_CPU = (GetTickCount() - Time_CPU) / 1000; // время окончания работы процесса (/ 1000- милисекунды переводим в секунды

cout << "\nИспользованное время процессора: " << fixed << (float)Time_CPU << "секунд" << "\n" << endl;

}

 

 

DWORD WINAPI ThRead_Function(LPVOID lpvThParam) // функция передаваемая в поток

{

Resultat += Sum_Element((int)lpvThParam);

return 0;

}

 

void Parallel_Computation()//функция параллельного (потогового) вычисления

{

cout << "Введите количество потоков: ";

cin >> Number_ThReads;

cout << "\nПроизводятся потоковые вычисления, Пожалуйста Подождите ....\n";

HANDLE *a_pointer_to_stream = new HANDLE[Number_ThReads]; //указатель на поток

DWORD Pointer_ThRead_Identifier; // идентификатор потока

 

Time_CPU=GetTickCount(); // время начала работы процесса

 

for(int t_id = 0; t_id < Number_ThReads; t_id++) // создание потоков

{

a_pointer_to_stream[t_id] = CreateThread(NULL, 0, ThRead_Function, (LPVOID)t_id, 0, &Pointer_ThRead_Identifier);

// функция создания новых потоков

}

 

for(int t_id = 0; t_id < Number_ThReads; t_id++)

{

WaitForSingleObject(a_pointer_to_stream[t_id], INFINITE); //Функция позволяет организовать ожидание завершения потока в милисекундах

// с заданным hHandle (a_pointer_to_stream[t_id]) ,

// (INFINITE - ждать вечно)

 

CloseHandle(a_pointer_to_stream[t_id]); //Функция завершения потока с заданным a_pointer_to_stream[tid]

}

cout.precision(16); //Задает число цифр для отображения числа с плавающей запятой.

cout << "\n\nРезультат расчета: " << double(Resultat) << endl;

cout << fixed; //fixed по умолчанию отображения чисел с плавающей запятой в экспоненциальном представлении.

cout.precision(2); //Задает число цифр для отображения числа с плавающей запятой.

Time_CPU = (GetTickCount() - Time_CPU) / 1000; // время окончания работы процесса (/ 1000- милисекунды переводим в секунды

cout << "\nИспользованное время процессора: " << fixed << (float)Time_CPU << "секунд" << "\n"<< endl;

delete[]a_pointer_to_stream; // удаление потоков

}

 

 

3. #include "stdafx.h"

4.

5. int n=10000000; // промежуток натуральных чисел

6. int kolProst=1;

7. double t1, t2;

8.

9. struct Data{

10. int min;

11. int max;

12. };

13.

14. DWORD WINAPI Poisk_prost(LPVOID lpvThParam){

15. Data *par=(Data*)lpvThParam;

16. int min=par->min;

17. int max=par->max;

18. int kol=0;

19. if (min%2==0) min++;

20. if (max%2==0) max--;

21. for (int i=min; i<=max; i+=2){

22. if (i==3) kol++;

23. for (int j = 3; j<i; j+=2){

24. if (i%j==0) {

25. break;

26. }

27. if (j*j-1>i) {

28. kol++;

29. break;

30. }

31. }

32. }

33. kolProst+=kol;

34. return 0;

35. }

36.

37. int main()

38. {

39. t1 = (double)clock();

40. setlocale(LC_ALL, "RUS");

41. cout << "Идет выполнение программы";

42. freopen("INPUT.TXT", "r", stdin);

43. freopen("OUTPUT.TXT", "w", stdout);

44. int kolPot=0;

45. cin >> kolPot;

46.

47. DWORD dwIdTh;

48. HANDLE *nt = new HANDLE[kolPot];

49.

50. Data str, *param;

51.

52. for(int i=1; i<=kolPot; i++){

53. str.min=(float)n/kolPot*(i-1);

54. str.max=(float)n/kolPot*i;

55. if ((str.min==0)&&(str.max>3)) {

56. str.min=3;

57. }

58.

59. if (str.max%2) str.max--;

60. param=&str;

61. nt[i-1]= CreateThread(NULL, 0, Poisk_prost, (LPVOID)param, 0, &dwIdTh);

62. WaitForSingleObject(nt[i-1], INFINITE);

63. }

64.

65. for(int i=0; i<kolPot; i++) CloseHandle(nt[i]);

66.

67. delete[] nt;

68. cout << "\n Количество потоков = " << kolPot;

69. cout.precision(16);

70. cout << "\n Количество = " << kolProst;

71. t2 = (double)clock();

72. std::cout << "\n Время выполнения = " << (t2-t1);

73. return 0;

74. }


Примеры входа и выхода программ.

 

Вычисление Интеграла (sin(x)dx) от 0 до Пи

 

Выбирете тип решения

1. Прямолинейное решение

2. Использовать параллельные потоки

3. Выход из програмы

Введите значение: 2

Введите количество потоков: 1

Производятся потоковые вычисления, Пожалуйста Подождите ....

Количество вычислений = 1000000000 Использован поток № 0

Результат расчета: 1.9999999999966300

Использованное время процессора: 59.00секунд

Для продолжения нажмите любую клавишу . . .

 

Вычисление Интеграла (sin(x)dx) от 0 до Пи

Выбирете тип решения

1. Прямолинейное решение

2. Использовать параллельные потоки

3. Выход из програмы

Введите значение: 2

Введите количество потоков: 2

Производятся потоковые вычисления, Пожалуйста Подождите ....

Количество вычислений = 500000000 Использован поток № 1

Количество вычислений = 500000000 Использован поток № 0

Результат расчета: 2.0000000000008273

Использованное время процессора: 30.00секунд

Для продолжения нажмите любую клавишу . . .

 

 

Вычисление Интеграла (sin(x)dx) от 0 до П

Выбирете тип решения

1. Прямолинейное решение

2. Использовать параллельные потоки

3. Выход из програмы

Введите значение: 2

Введите количество потоков: 3

Производятся потоковые вычисления, Пожалуйста Подождите ....

Количество вычислений = 333333334 Использован поток № 0

Количество вычислений = 333333333 Использован поток № 2

Количество вычислений = 333333333 Использован поток № 1

Результат расчета: 2.0000000000004676

Использованное время процессора: 26.00секунд

Для продолжения нажмите любую клавишу . . .

 

 

Вычисление Интеграла (sin(x)dx) от 0 до Пи

Выбирете тип решения

1. Прямолинейное решение

2. Использовать параллельные потоки

3. Выход из програмы

Введите значение: 2

Введите количество потоков: 14

Производятся потоковые вычисления, Пожалуйста Подождите ....

Количество вычислений = 71428572 Использован поток № 5

Количество вычислений = 71428571 Использован поток № 7

Количество вычислений = 71428572 Использован поток № 2

Количество вычислений = 71428572 Использован поток № 1

Количество вычислений = 71428571 Использован поток № 9

Количество вычислений = 71428571 Использован поток № 13

Количество вычислений = 71428571 Использован поток № 11

Количество вычислений = 71428572 Использован поток № 3

Количество вычислений = 71428572 Использован поток № 0

Количество вычислений = 71428572 Использован поток № 4

Количество вычислений = 71428571 Использован поток № 12

Количество вычислений = 71428571 Использован поток № 6

Количество вычислений = 71428571 Использован поток № 10

Количество вычислений = 71428571 Использован поток № 8

Результат расчета: 1.9999999999998799

Использованное время процессора: 27.00секунд

Для продолжения нажмите любую клавишу . . .

 

 

Количество потоков = 1

Количество = 5761455

Время выполнения = 700206

 

Количество потоков = 2

Количество = 5761455

Время выполнения = 687755

 

Количество потоков = 3

Количество = 5761455

Время выполнения = 654174

 

Количество потоков = 4

Количество = 5761455

Время выполнения = 664587

 

Количество потоков = 5

Количество = 5761455

Время выполнения = 660037

 

Количество потоков = 10

Количество = 5761455

Время выполнения = 661512

 

Количество потоков = 15

Количество = 5761455

Время выполнения = 651544

 

Количество потоков = 20

Количество = 5761455

Время выполнения = 652743

 

Количество потоков = 30

Количество = 5761455

Время выполнения = 655568

 

Количество потоков = 50

Количество = 5761455

Время выполнения = 665444

 

Расчет от 0 до pi

 

N п/п Количество потоков Время, с

 

 

При 100млн 5761455

 

N п/п Количество потоков Время, мс

 

 

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

Данные исследования выполнялись под операционной системой Windows 7 Максимальная 32-раз. ОС, памятью 2,5 ГБ, двухядерный процессор 3.01 Гц

 

В обоих программах зависимость выполнения расчета зависит от количества потоках. В интервале от 1 до 20 потоках зависимость пропорциональная т.е. чем больше потомков мы выделяет тем скорее программа выполнит требуемый расчет, и обратно пропорциональна если количество потоков превышает 20 (т.е. программа станет выполнят требуемую процедуру дольше)


Выводы по работе

 

В ходе данной лабораторной работы я научился выделять несколько потоков для программы, учитывать время производительности от количества потоков.