Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2Phần code • Thread=8 Hình 2.1.5: Real time of dotpodmutex.c with thread=8... Comparison chart between dotprodserial.c and dotprodmute
Trang 1BÁO CÁO BÀI TẬP LỚN
HỆ ĐIỀU HÀNH
Đề tài : PThread and Multicore programming
GVHD: GV: Nguyễn Quang Hùng
Thực hiện: Nguyễn Lê Minh Bảo
Hà Việt Đức -Đoàn Thảo Nhi - 2014010 Trịnh Tiến Đạt - 2012959
Từ Hoàng Phiếm - 2014112
Trang 2Mục lục
1 Phần Lý thuyết . 3
2 Phần code . 4
2.1 Mutexes . 4
2.1.1 Review, compile and run the dotprodserial.c program 4
2.1.2 Review, compile and run the dotprodmutex.c program 4
2.1.3 Execute the dotprodmutex.c program with thread are arranged 7
2.2 Condition Variables . 11
2.2.1 Review, compile and run the condvar.c program 11
2.2.2 Review, compile, run the bug4.c program and fix the problem 13
2.3 Figure out and fix the global sum . 14
2.4 Compile and run arrayloops.c . 19
Trang 4Phần code Phần 2
Mutexes
2.1
2.1.1 Review, compile and run the dotprodserial.c program
The dotprodserial.c program used to calculate the indirection of two vectors with
length =100000 Two vectors is calculated to be shown struct DOTDATA This
pro-gram does by running sequentially on a thread
Output : Result When dotprodserial.c run
Hình 2.1.1: Real time of dotpodserial.c.
2.1.2 Review, compile and run the dotprodmutex.c program
The dotprodmutex.c program used to calculate the direction of two vectors with length=100000 But here is the difference:
• In main() function has initialize with the number of thread is 4 to run parallel processes
• In dotprod() function use pthreadmutexlock và pthreadmutexunlock is one of the main means to synchronize flows and to protect shared data when multiple writing happens
Output : Result when the dotprodmutex.c run
Trang 5Hình 2.1.2: Real time of dotpodmutex.c
Output : The dotprodmutex.c run with thread = 2, 4, 8, 16, 32 và sum=100000
• Thread=2
Hình 2.1.3: Real time of dotpodmutex.c with thread=2.
• Thread=4
Hình 2.1.4: Real time of dotpodmutex.c with thread=4.
Trang 6Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
• Thread=8
Hình 2.1.5: Real time of dotpodmutex.c with thread=8.
• Thread=16
Hình 2.1.6: Real time of dotpodmutex.c with thread=16.
Trang 7• Thread=32
Hình 2.1.7: Real time of dotpodmutex.c with thread=32.
Comparison chart between dotprodserial.c and dotprodmutex.c
2.1.3 Execute the dotprodmutex.c program with thread are arranged
Explain the code :
• Wanting the thread to be printed in the same self, we need to let pthreadjoin within for the time of creating pthreadcreate Because the thread is created it will run and wait for pthreadjoin to pay the result, then create a new thread new should order Print it will be true
• As for pthreadjoin at another for another round, it only works to wait all the thread returns the result before the main () stops
• If there is no pthreadjoin, when the main () is finished, no matter whether other threads are finished or not, the program is terminated
Code after fixing :
Trang 8Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA;
/* Define globally accessible variables and a mutex */
#define NUMTHRDS 4
#define VECLEN 100000
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;
void *dotprod(void *arg)
{
/* Define and use local variables for convenience */
int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;
len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b;
/*
Trang 9Perform the dot product and assign result
to the appropriate variable in the structure
*/
mysum = 0;
for (i=start; i<end ; i++)
{
mysum += (x[i] * y[i]);
}
/*
Lock a mutex prior to updating the value in the shared
structure, and unlock it upon updating
*/
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
printf("Thread %ld did %d to %d: mysum=%f global
sum=%f\n",offset,start,end,mysum,dotstr.sum);
pthread_mutex_unlock (&mutexsum);
pthread_exit((void*) 0);
}
int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
pthread_attr_t attr;
/* Assign storage and initialize values */
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
for (i=0; i<VECLEN*NUMTHRDS; i++) {
a[i]=1;
b[i]=a[i];
}
Trang 10Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;
pthread_mutex_init(&mutexsum, NULL);
/* Create threads to perform the dotproduct */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(i=0;i<NUMTHRDS;i++)
{
/* Each thread works on a different set of data
* The offset is specified by 'i' The size of
* the data for each thread is indicated by VECLEN
*/
pthread_create(&callThd[i], &attr, dotprod, (void *)i); /* Wait on the other threads- Fix*/
pthread_join(callThd[i], &status);
}
pthread_attr_destroy(&attr);
/* After joining, print out the results and cleanup */
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
Trang 11Condition Variables
2.2
2.2.1 Review, compile and run the condvar.c program
Bài code mẫu condvar.c sử dụng Pthread contidion variables Ở dưới hàm main(), chúng ta sẽ tạo ra 3 thread Hai trong số chúng sẽ tăng biến count, trong khi đó, thread còn lại sẽ xem giá trị của count Khi biến count tăng lên một giới hạn cho trước, waiting thread được báo hiệu bởi một trong 2 thread tăng biến count Waiting thread sẽ "awakens" và sau đó sửa đổi count Chương trình sẽ tiếp tục cho đến khi các thread đạt tới giá trị TCOUNT Cuối cùng, chương trình sẽ in ra giá trị cuối cùng của biến count.
OUTPUT:
Trang 12Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
inc_count(): thread 3, count = 1, unlocking mutex
inc_count(): thread 2, count = 2, unlocking mutex
Starting watch_count(): thread 1
watch_count(): thread 1 Count= 2 Going into wait
inc_count(): thread 3, count = 3, unlocking mutex
inc_count(): thread 2, count = 4, unlocking mutex
inc_count(): thread 3, count = 5, unlocking mutex
inc_count(): thread 2, count = 6, unlocking mutex
inc_count(): thread 3, count = 7, unlocking mutex
inc_count(): thread 2, count = 8, unlocking mutex
inc_count(): thread 3, count = 9, unlocking mutex
inc_count(): thread 2, count = 10, unlocking mutex
inc_count(): thread 3, count = 11, unlocking mutex
inc_count(): thread 2, count = 12 Threshold reached Just sent signal
inc_count(): thread 2, count = 12, unlocking mutex
watch_count(): thread 1 Condition signal received Count= 12
watch_count(): thread 1 Updating the value of count
watch_count(): thread 1 count now = 137
watch_count(): thread 1 Unlocking mutex
inc_count(): thread 3, count = 138, unlocking mutex
inc_count(): thread 2, count = 139, unlocking mutex
inc_count(): thread 3, count = 140, unlocking mutex
inc_count(): thread 2, count = 141, unlocking mutex
inc_count(): thread 3, count = 142, unlocking mutex
inc_count(): thread 2, count = 143, unlocking mutex
inc_count(): thread 3, count = 144, unlocking mutex
inc_count(): thread 2, count = 145, unlocking mutex
Main(): Waited and joined with 3 threads Final value of count = 145 Done
Trang 132.2.2 Review, compile, run the bug4.c program and fix the problem
1 Run the bug4.c program:
Hình 2.2.1: The result after running the bug4.c program.
2 Run the bug4.c program:
Trang 14Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
Figure out and fix the global sum
2.3
Result bug6.c
#First
thread: 0 starting start=0 end=99999
thread: 2 starting start=200000 end=299999
thread: 2 done Global sum now is=103536
thread: 3 starting start=300000 end=399999
thread: 3 done Global sum now is=209650
thread: 0 done Global sum now is=144053
thread: 5 starting start=500000 end=599999
thread: 4 starting start=400000 end=499999
thread: 5 done Global sum now is=244978
thread: 6 starting start=600000 end=699999
thread: 4 done Global sum now is=354856
thread: 7 starting start=700000 end=799999
thread: 6 done Global sum now is=366826
thread: 7 done Global sum now is=462298
thread: 1 starting start=100000 end=199999
thread: 1 done Global sum now is=562298
Final Global Sum=562298
#Second
thread: 0 starting start=0 end=99999
thread: 1 starting start=100000 end=199999
thread: 1 done Global sum now is=123218
thread: 0 done Global sum now is=133169
thread: 3 starting start=300000 end=399999
thread: 4 starting start=400000 end=499999
thread: 3 done Global sum now is=258391
thread: 5 starting start=500000 end=599999
thread: 4 done Global sum now is=281444
thread: 6 starting start=600000 end=699999
thread: 5 done Global sum now is=367357
thread: 7 starting start=700000 end=799999
Trang 15Giải thích: Do biến sum là biến global scope và các threads truy cập vào cùng 1
địa chỉ biến sum nên sẽ xảy ra tình trạng race condition Giải pháp được đưa ra là sử dụng mutex clock
Trang 16Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/* Define global data where everyone can see them */
#define NUMTHRDS 8
#define VECLEN 100000
pthread_mutex_t mutexsum;
int *a, *b;
long sum = 0.0;
void *dotprod(void *arg) {
/* Each thread works on a different set of data
* The offset is specified by the arg parameter The size of
* the data for each thread is indicated by VECLEN
*/
int i, start, end, offset, len;
long tid;
long local_sum = 0;
tid = (long)arg;
offset = tid;
len = VECLEN;
start = offset*len;
end = start + len;
/* Perform my section of the dot product */
printf("thread: %ld starting start=%d
end=%d\n",tid,start,end-1);
for (i=start ; i < end ; i++) local_sum += (a[i] *
b[i]);
printf("thread: %ld done Global sum now
is=%li\n",tid,sum);
Trang 17int main (int argc, char *argv[]) {
long i;
void *status;
pthread_t threads[NUMTHRDS];
pthread_attr_t attr;
/* Assign storage and initialize values */
a = (int*) malloc (NUMTHRDS*VECLEN*sizeof(int));
b = (int*) malloc (NUMTHRDS*VECLEN*sizeof(int));
for (i=0 ; i < VECLEN*NUMTHRDS ; i++) a[i] = b[i] = 1;
/* Initialize mutex variable */
pthread_mutex_init(&mutexsum, NULL);
/* Create threads as joinable, each of which will
execute the dot product
* routine Their offset into the global vectors is specified by passing
* the "i" argument in pthread_create()
*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_JOINABLE);
for (i=0 ; i < NUMTHRDS ; i++)
pthread_create(&threads[i], &attr, dotprod, (void
*)i);
pthread_attr_destroy(&attr);
/* Wait on the other threads for final result */
for (i=0 ; i < NUMTHRDS ; i++)
pthread_join(threads[i], &status);
/* After joining, print out the results and cleanup */
printf ("Final Global Sum=%li\n",sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
Trang 18Trường Đại học Bách Khoa Thành phố Hồ Chí Minh Phần 2
Phần code
Result bug6fix.c
#First
thread: 0 starting start=0 end=99999
thread: 1 starting start=100000 end=199999
thread: 0 done Global sum now is=0
thread: 2 starting start=200000 end=299999
thread: 1 done Global sum now is=100000
thread: 3 starting start=300000 end=399999
thread: 2 done Global sum now is=200000
thread: 4 starting start=400000 end=499999
thread: 4 done Global sum now is=300000
thread: 5 starting start=500000 end=599999
thread: 3 done Global sum now is=400000
thread: 6 starting start=600000 end=699999
thread: 5 done Global sum now is=500000
thread: 6 done Global sum now is=600000
thread: 7 starting start=700000 end=799999
thread: 7 done Global sum now is=700000
Final Global Sum=800000
#Second
thread: 0 starting start=0 end=99999
thread: 0 done Global sum now is=0
thread: 1 starting start=100000 end=199999
thread: 2 starting start=200000 end=299999
thread: 1 done Global sum now is=100000
thread: 3 starting start=300000 end=399999
thread: 2 done Global sum now is=200000
thread: 4 starting start=400000 end=499999
thread: 3 done Global sum now is=300000
thread: 5 starting start=500000 end=599999
thread: 4 done Global sum now is=400000
thread: 6 starting start=600000 end=699999
thread: 5 done Global sum now is=500000
thread: 7 starting start=700000 end=799999
thread: 6 done Global sum now is=600000
Trang 19Compile and run arrayloops.c
2.4
Arrayloops.c là 1 ví dụ khác của việc dùng mutex để cập nhật biến toàn cục sum
Results:
Thread 0 doing iterations 0 to 249999
Thread 2 doing iterations 500000 to 749999
Thread 3 doing iterations 750000 to 999999
Thread 1 doing iterations 250000 to 499999
Done Sum= 4.999995e+11
Check Sum= 4.999995e+11