9. Parallel Computing tizimida Windows API dan foydalanish.
Jarayonning bajarilishi kontekstida bir nechta oqimlar ishlashi mumkin. Windows operatsion tizimida ip - bu OS dasturni bajarish uchun protsessor vaqtini ajratadigan bajarish birligi. Oqimlar bilan ishlash uchun WIndows API-da mavjud funktsiyalarni ko'rib chiqing. CreateThread funksiyasi ip yaratish uchun ishlatiladi. HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpSecAttr, SIZE_T StackSize, LPTHREAD_START_ROUTINE lpStartFuncAddr, LPVOID p, DWORD dwCreatParam, LPDWORD thrId); bu yerda: lpSecAttr – SECURITY_ATTRIBUTES ko‘rsatkichi, bu parametrni NULL ga ham o‘rnatish mumkin, keyin qaytarilgan deskriptor meros qilib olinmaydi StackSize – stekning dastlabki hajmi (baytlarda ko‘rsatilgan). Parametr sifatida nolni belgilasangiz, u holda tizim standart stek hajmini o'rnatadi144 lpStartFuncAddr - bu ip tomonidan bajariladigan funktsiyaning ko'rsatkichi, shuning uchun bu erda ipning boshlang'ich manzili ko'rsatiladi; bu funktsiya dasturda quyidagicha belgilanishi kerak: DWORD WINAPI FunctionName(LPVOID) p o‘zgaruvchiga ko‘rsatgich bo‘lib, uni ip orqali bajariladigan FunctionName(LPVOID p) funksiyasiga o‘tkazishimiz kerak bo‘ladi; ipni yaratish. Siz quyidagilarni belgilashingiz mumkin: 0 (keyin ip yaratilgandan so'ng darhol ishlay boshlaydi), CREATE_SUSPENDED (ip ResumeThread funksiyasi bajarilgandan keyin ishlay boshlaydi, bu haqda keyinroq) quyida uning ta'rifidan ko'rinib turibdiki, u emas. hech narsani qaytarmang. Ushbu funktsiya chaqirilganda yoki ip ipda bajarilayotgan WINAPI FunctionName(LPVOID) DWORD funktsiyasidan qaytib kelganda, ip to'xtashi mumkin.
VOID WINAPI ExitThread(DWORD dwExitCode); dwExitCode-da biz ipni tugatish kodini joylashtiramiz. Tarmoqni to'xtatib turish uchun siz SuspendThread funksiyasidan foydalanishingiz kerak. Agar ip muvaffaqiyatli to'xtatilsa, funktsiya ushbu ipning oldingi to'xtash sonini qaytaradi, agar SuspendThread funksiyasi bajarilmasa, u -1 ni qaytaradi. DWORD WINAPI SuspendThread(HANDLE thread); ip - osiladigan ipning tutqichi. U kirish huquqiga ega boʻlishi kerak: THREAD_SUSPEND_RESUME Agar siz ushbu mavzuni davom ettirmoqchi boʻlsangiz, ResumeThread funksiyasini chaqirishingiz kerak. Muvaffaqiyatli bo'lsa, ipning oldingi to'xtash soni qaytariladi, aks holda -1. DWORD WINAPI ResumeThread(HANDLE thread);145 ip – davom ettiriladigan ipning dastasi. U kirish huquqiga ega bo'lishi kerak: THREAD_SUSPEND_RESUME Endi ikki o'lchovli matritsa satrlarini parallel ko'p tarmoqli yaratish va qayta ishlashni amalga oshiradigan dastur misolini ko'rib chiqamiz. Ya'ni, har bir alohida ip matritsa qatorini hosil qiladi va bu qatorning toq elementlarining mahsulotini topadi. Parametr sifatida biz har bir oqimga matritsa qatorini va elementlar mahsuloti natijasini saqlaydigan strukturaga ko'rsatgich o'tkazamiz. Kerakli kutubxonalarni ulaymiz: natijalarni ekranda ko'rsatish, WinAPI funksiyalaridan foydalanish va tasodifiy sonlar generatorining ishga tushirish elementi sifatida vaqtdan foydalanish uchun.
#include
#include
#include
Matritsa hajmini saqlash uchun konstantani aniqlaymiz (bu misolda 4x4 matritsa).
#define MATRIX_SIZE 4
Keling, matritsa qatorini, ushbu qatorning toq elementlarini ko'paytirish natijasini va ushbu mavzudagi tasodifiy sonlar generatorini ishga tushirish uchun ishlatiladigan tasodifiy sonni saqlaydigan tuzilmani aniqlaylik (agar siz hamma uchun bir xil generatordan foydalansangiz). iplar, keyin bir vaqtning o'zida bajarilishi tufayli barcha qatorlar uchun bir xil raqamlar hosil bo'ladi).
struct row
{
int value[MATRIX_SIZE];
int result;
int rnd;
};
Функция DWORD WINAPI generateAndCalc(void *data), которую будут
исполнять потоки (с комментариями):
DWORD WINAPI generateAndCalc(void *data)
{
//преобразуем полученные данные к типу структуры
row *r = (row *) data;
//инициализируем генератор случайных чисел полученным числом
srand(r->rnd);
//генерируем элементы строки
for (int i = 0; i < MATRIX_SIZE; i++)
{
r->value[i] = rand() % 10;
}
//находим произведение нечетных элементов
r->result = 1;
for (int i = 0; i < MATRIX_SIZE; i += 2)
{
r->result *= r->value[i];
}
izohlar bilan main() funktsiyasi
int main()
{
//инициализируем генератор случайных чисел
srand(time(NULL));
//определяем дескрипторы потоков,
//идентификаторы потоков и структуры для строк матрицы
HANDLE thread[MATRIX_SIZE];
DWORD thrId[MATRIX_SIZE];147
row rows[MATRIX_SIZE];
for (int i = 0; i < MATRIX_SIZE; i++)
{
//генерируем случайные числа для каждой строки
rows[i].rnd = rand();
//создаем потокиPP
thread[i] = CreateThread(NULL, 0, &generateAndCalc, &rows[i], 0,
&thrId[i]);
}
barcha mavzular tugashini kuting
WaitForMultipleObjects(MATRIX_SIZE, thread, TRUE, INFINITE);
//выводим результат работы программы на экран
for (int i = 0; i < MATRIX_SIZE; i++)
{
for (int j = 0; j < MATRIX_SIZE; j++)
{
printf(" %d", rows[i].value[j]);
}
printf(" | multipl = %d\n", rows[i].result);
}
return 0;
}
Dastur quyidagi skrinshotda ko'rsatilgan.
Do'stlaringiz bilan baham: |