Имени А.Г. и Н.Г. Столетовых
Министерство образования и науки РФ
Федеральное государственное бюджетное образовательное учреждение
Высшего профессионального образования
Владимирский государственный университет
имени А.Г. и Н.Г. Столетовых
(ВлГУ)
Лабораторная работа № 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 (т.е. программа станет выполнят требуемую процедуру дольше)
Выводы по работе
В ходе данной лабораторной работы я научился выделять несколько потоков для программы, учитывать время производительности от количества потоков.