Хамгаалах эцсийн хугацаа: 3-р долоо хоног
M ширхэг мөртэй, K ширхэг баганатай A матрицыг, К ширхэг мөртэй N ширхэг баганатай В матрицаар үржүүлэхэд M ширхэг мөртэй, N ширхэг баганатай С матриц үүснэ. С матрицын i-р мөрийн j-р багана дээрх элементийн (Cij) утга нь А матрицын i-р мөрийн элементүүдийг В матрицийн j-р баганын элементүүдээр харгалзуулан үржүүлж нэмсэнтэй тэнцүү. Томъёог дараах байдлаар бичиж болно:
Жишээ нь хэрэв А матриц 3х2 хэмжээтэй, В матриц 2х3 хэмжээтэй байсан бол C3,1 элемент нь А3,1 х В1,1 болон А3,2 х В2,1 үржвэрүүдийн нийлбэртэй тэнцүү байна.
Энэ лабораторын ажлаар Ci,j элемент бүрийг нэг хуулбар процессоор тооцоолж олно. Ингэснээр бид M x N тооны хуулбар процесстой болно. Гол буюу эцэг хуулбар процесс нь А болон В матрицын анхны утгуудыг олгох ба А, В-гийн үржвэрийн утгыг хадгалах С матрицад хангалттай санах ой хуваарилж өгнө. Эдгээр матрицуудыг глобал байдлаар зарлах ба бүх хуулбар процессууд А, В, С матрицуудад хандаж чадах болно.
А болон В матрицыг анхны утгатайгаар доорх байдлаар зарлаж болно:
#define M 3
#define K 2
#define N 3
int A[M][K]={{1,4}, {2,5}, {3,6}};
int B[K][N]={{8,7,6}, {5,4,3}};
int C[M][N];
Мөн эдгээр утгуудыг файлаас уншдаг байж болно.
Хуулбар процесс бүрт параметр дамжуулах
Эцэг хуулбар процесс М х N ширхэг хуулбар процесс үүсгээд матрицын үржвэрийг тооцоолуулахын тулд тус бүрт нь i-р мөр болон j-р багана дахь утгуудыг дамжуулна. Энэ нь хуулбар процесс бүрт хоёр параметр дамжуулахыг шаардана. Pthreads болон Win32 – ыг ашиглах үед хамгийн амархан арга нь struct түлхүүр үгийг ашиглан бүтэц үүсгэх юм. Бүтцийн гишүүд нь i болон j болох ба бүтцийг доорх байдлаар зарлана:
/*хуулбар процессууд руу өгөгдөл дамжуулахад зориулсан бүтэц*/
struct v{
int i; /*мөр*/
int j; /*багана*/
};
Pthreads болон Win32-ын аль аль нь доор үзүүлсэнтэй төстэй байдлаар хуулбар процессуудаа үүсгэнэ:
/* M*N ширхэг хуулбар процесс үүсгэх */
for(i=0;i<M;i++){
for(j=0;j<N;j++){
struct v *data=(struct v *)malloc(sizeof(struct v));
data->i=i;
data->j=j;
/*Энд хуулбар процессыг үүсгэхдээ data-г параметр болгон дамжуулна*/
}
}
Заагч data-г pthread_create() функц руу (Pthreads) эсвэл CreateThread() функц руу (Win32) дамжуулах ба тэдгээр нь тусдаа хуулбар процесс байдлаар ажиллах функц рүү параметр байдлаар дамжуулна.
Java-гийн хуулбар процессуудын хооронд өгөгдөл дамжуулах нь Pthreads болон Win32-ынхоос ялгаатай. Нэг арга нь гол хуулбар процесс A, B, C матрицуудыг үүсгэж, анхны утгыг нь олгох юм. Дараа нь уг гол хуулбар процесс бусад хуулбар процессуудаа үүсгэн, тэдний байгуулагч функц тус бүрт гурван матрицыг, мөрийн дугаар i, баганын дугаар j-ийн хамт дамжуулна. Иймд хуулбар процесс нь дараах хэлбэртэй байна:
public class WorkThread implements Runnable{
private int row;
private int col;
private int [] [] A;
private int [] [] B;
private int [] [] C;
public WorkThread(int row, int col, int [] [] A, int [] [] B, int [] [] C){
this.row=row;
this.col=col;
this.A=A;
this.B=B;
this.C=C;
}
public void run(){
/*C[row][col] дахь матрицын үржвэрийг тооцоолох*/
}
}
Хуулбар процессуудыг дуусахыг хүлээх
Бүх хуулбар процесс дууссаны дараа гол хуулбар процесс С матриц дахь үржвэрийг гаргана. Иймд гол хуулбар процесс үржвэрийг хэвлэхийн тулд бусад бүх хуулбарыг ажиллаж дуусахыг хүлээнэ. Нэг хуулбар процесс нөгөөгөө дуусахыг хүлээх байдлыг хэд хэдэн аргаар хийж болно. 4.3-т (Section 4.3) Win32, Pthreads болон Java-гийн хуулбарын сангийн функцуудыг ашиглан яаж хүү процессыг дуусахыг хүлээх тухай тайлбарласан. Win32 нь WaitForSingleObject() функцтэй бол Pthreads болон Java нь харгалзан pthread_join() болон join() функцуудыг ашигладаг. Гэвч эдгээр програмын жишээнд эцэг процесс зөвхөн ганц хүү хуулбар процессоо дуусахыг хүлээж байгаа ба энэ лабораторын ажил нь олон хуулбар процессыг хүлээхийг шаардаж байгаа.
#define NUM_THREADS 10
/*нэгтгэх гэж байгаа хуулбар процессуудын хүснэгт*/
pthread_t workers[NUM_THREADS];
for(int i=0; i<NUM_THREADS; i++)
pthread_join(workers[i], NULL);
Зураг 4.12 Арван хуулбар процессыг нэгтгэх Pthread код
4.3.2 – т нэг хуулбар процессыг дуусахыг хүлээдэг WaitForSingleObject() функцийг авч үзсэн. Win32 API – д мөн олон хуулбар процесс дуусахыг хүлээдэг WaitForMultipleObjects() функц байдаг. WaitForMultipleObjects() функц рүү дөрвөн параметр дамжуулагдана:
final static int NUM_THREADS=10;
/*нэгтгэх гэж байгаа хуулбар процессуудын хүснэгт*/
Thread[] workers=new Thread[NUM_THREADS];
for(int i=0; i<NUM_THREADS; i++){
try{
workers[i].join();
}catch(InterruptedException ie){}
}
Зураг 4.13 Арван хуулбар процессыг нэгтгэх Java код
Жишээ нь, хэрэв THandles нь N хэмжээтэй Handle хуулбар процессын объектууд бол эцэг процесс хүү процессуудаа бүгдийг дуусахыг дараах функцийн дуудалтаар гүйцэтгэж болно:
WaitForMultipleObjects(N, THandles, TRUE, INFINITE);
Хэд хэдэн хуулбар процессын дуусахыг хүлээх өөр нэг хялбар арга нь Pthreads-ын pthread_join() болон Java-гийн join() функцээр нэгтгэх ажиллагааг for давталтан дотор хийх явдал юм. Жишээ нь та арван хуулбар процессыг Зураг 4.12-т үзүүлснээр Pthread код ашиглан нэгтгэж болно. Үүнтэй адил кодыг Java – гийн хуулбар процесс ашиглан бичсэнийг Зураг 4.13-т үзүүлэв.