diff --git a/exp1/badcount b/exp1/badcount index 23534af..50e9bf9 100755 Binary files a/exp1/badcount and b/exp1/badcount differ diff --git a/exp1/badcount.c b/exp1/badcount.c new file mode 100644 index 0000000..2f578ce --- /dev/null +++ b/exp1/badcount.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + + +void *increase(void *vargp); +void *decrease(void *vargp); +int cnt = 0; + + +int main(int argc, char **argv) +{ + unsigned int niters; + pthread_t t1,t2; + + if (argc != 2) + { + printf("Usage: %s \n", argv[0]); + exit(2); + } + niters = atoll(argv[1]); + + pthread_create(&t1,NULL,increase,(void *)niters); + pthread_create(&t2,NULL,decrease,(void *)niters); + pthread_join(t1,NULL); + pthread_join(t2,NULL); + + if (cnt != 0) + { + printf("Error! cnt=%d\n", cnt); + } + else + { + printf("Correct! cnt=%d\n", cnt); + } + exit(0); +} + +void *increase(void *vargp) +{ + unsigned i ,niters = (unsigned int)vargp; + for ( i = 0; i < niters; i++) + { + cnt++; + } + return NULL; +} + +void *decrease(void *vargp) +{ + unsigned i, niters = (unsigned int)vargp; + for ( i = 0; i < niters; i++) + { + cnt--; + } + return NULL; +} \ No newline at end of file diff --git a/exp1/psum64.c b/exp1/psum64.c new file mode 100644 index 0000000..70f5bfb --- /dev/null +++ b/exp1/psum64.c @@ -0,0 +1,79 @@ +/*任务4(必做):编译、测试和运行示例程序psum64.c +1)测量线程数为1、2、4、8、16时程序的执行时间,计算加速比和效率,并做出解释。 +2)改写该程序psum64.c,保存为task64.c,实现计算02+12+… +(n-1)2功能。 +*/ + +#include +#include +#include +#include +#include + +#define MAXTHREADS 16 + +void *sum(void *vargp); + +unsigned long long psum64[MAXTHREADS]; +unsigned long long nelems_per_thread; + +int main(int argc, char **argv) +{ + unsigned long long i,nelems,log_nelems,nthreads,result = 0; + pthread_t tid[MAXTHREADS]; + int myid[MAXTHREADS]; + + if(argc != 3) + { + printf("Usage: %s \n",argv[0]); + exit(0); + } + nthreads = atoi(argv[1]); + log_nelems = atoi(argv[2]); + nelems = (1LL << log_nelems); + nelems_per_thread = nelems / nthreads; + + for ( i = 0; i < nthreads; i++) + { + myid[i] = i; + pthread_create(&tid[i],NULL,sum,&myid[i]); + } + + for ( i = 0; i < nthreads; i++) + { + pthread_join(tid[i],NULL); + } + + for ( i = 0; i < nthreads; i++) + { + result += psum64[i]; + } + + if (result == (nelems*(nelems-1))/2) + { + printf("Correct result: %ld\n",result); + } + else + { + printf("Wrong result: %ld\n",result); + } + + exit(0); +} + + + +void *sum(void *vargp) +{ + int myid = *((int *)vargp); + unsigned long long begin = myid * nelems_per_thread; + unsigned long long end = begin + nelems_per_thread; + unsigned long long i,lsum=0; + + for (i = begin; i < end; i++) + { + lsum += i; + } + + psum64[myid] = lsum; + return NULL; +} \ No newline at end of file diff --git a/exp1/task61 b/exp1/task61 index 1b8468a..6337b1d 100755 Binary files a/exp1/task61 and b/exp1/task61 differ diff --git a/exp1/task61.c b/exp1/task61.c index 67dee6d..8560f8e 100644 --- a/exp1/task61.c +++ b/exp1/task61.c @@ -31,7 +31,7 @@ void *wokerT3(void *vargp) for(int i=0; i<5; i++) { time_t t = time(NULL); - printf("Current time %s\n",ctime(&t)); + printf("Current time %s",ctime(&t)); int sleep_time = rand() % 5 + 1; sleep(sleep_time); } diff --git a/exp1/task62 b/exp1/task62 new file mode 100755 index 0000000..0bb620f Binary files /dev/null and b/exp1/task62 differ diff --git a/exp1/task62.c b/exp1/task62.c index 717bcd1..2a3c4f4 100644 --- a/exp1/task62.c +++ b/exp1/task62.c @@ -5,51 +5,29 @@ #include #include +void *increase(void *vargp); +void *decrease(void *vargp); int cnt = 0; sem_t mutex; -void *increase(void *vargp) -{ - unsigned int niters = (unsigned int)vargp; - for (unsigned int i = 0; i < niters; i++) - { - sem_wait(&mutex); - cnt++; - sem_post(&mutex); - } - return NULL; -} - -void *decrease(void *vargp) -{ - unsigned int niters = (unsigned int)vargp; - for (unsigned int i = 0; i < niters; i++) - { - sem_wait(&mutex); - cnt--; - sem_post(&mutex); - } - return NULL; -} - int main(int argc, char **argv) { unsigned int niters; pthread_t t1,t2; - + if (argc != 2) { printf("Usage: %s \n", argv[0]); exit(2); } niters = atoll(argv[1]); - + sem_init(&mutex, 0, 1); - pthread_create(&t1,NULL,increase,(void*)niters); - pthread_create(&t2,NULL,decrease,(void*)niters); + pthread_create(&t1,NULL,increase,(void *)niters); + pthread_create(&t2,NULL,decrease,(void *)niters); pthread_join(t1,NULL); pthread_join(t2,NULL); - + if (cnt != 0) { printf("Error! cnt=%d\n", cnt); @@ -60,4 +38,28 @@ int main(int argc, char **argv) } sem_destroy(&mutex); exit(0); +} + +void *increase(void *vargp) +{ + unsigned i ,niters = (unsigned int)vargp; + for ( i = 0; i < niters; i++) + { + sem_wait(&mutex); + cnt++; + sem_post(&mutex); + } + return NULL; +} + +void *decrease(void *vargp) +{ + unsigned i, niters = (unsigned int)vargp; + for ( i = 0; i < niters; i++) + { + sem_wait(&mutex); + cnt--; + sem_post(&mutex); + } + return NULL; } \ No newline at end of file diff --git a/exp1/task63 b/exp1/task63 new file mode 100755 index 0000000..7a7c4af Binary files /dev/null and b/exp1/task63 differ diff --git a/exp1/task63.c b/exp1/task63.c index e4e3a28..3387ad4 100644 --- a/exp1/task63.c +++ b/exp1/task63.c @@ -1,3 +1,10 @@ +/* +编写一个多线程程序task63.c,创建k个生产者线程和m个消费者线程, +每个生产者线程产生若干个随机数,通过由N个单元构成的缓冲区,发送给消费者线程, +进行输出显示,产生Pthread信号量实现生产者/消费者线程间同步,并且设计一种方案对程序正确性进行验证。 +提示:一种非严谨的简单验证方案是,将生产者线程产生的所有随机数相加得到一个和,消费者线程接收到的所有随机数相加得到另一个和,验证两个和是否一致来来验证程序正确性 + +*/ #include #include #include @@ -5,3 +12,181 @@ #include #include +#define POISON -1 + +typedef struct { + int *buf; + int n; + int inpos; + int outpos; + sem_t mutex; + sem_t slots; + sem_t items; +} sbuf_t; + +long long produced_sum = 0; +long long consumed_sum = 0; +sem_t sum_mutex; +int total_items; + +void sbuf_init(sbuf_t *sp, int n) +{ + sp->buf = (int *)malloc(n*sizeof(int)); + sp->n = n; + sp->inpos = 0; + sp->outpos = 0; + sem_init(&sp->mutex, 0, 1); + sem_init(&sp->slots, 0, n); + sem_init(&sp->items, 0, 0); +} + +void sbuf_deinit(sbuf_t *sp) +{ + free(sp->buf); + sem_destroy(&sp->mutex); + sem_destroy(&sp->slots); + sem_destroy(&sp->items); +} + +void sbuf_insert(sbuf_t *sp, int item) +{ + sem_wait(&sp->slots); + sem_wait(&sp->mutex); + sp->buf[sp->inpos] = item; + sp->inpos = (sp->inpos + 1) % sp->n; + sem_post(&sp->mutex); + sem_post(&sp->items); +} + +int sbuf_remove(sbuf_t *sp) +{ + sem_wait(&sp->items); + sem_wait(&sp->mutex); + int item = sp->buf[sp->outpos]; + sp->outpos = (sp->outpos + 1) % sp->n; + sem_post(&sp->mutex); + sem_post(&sp->slots); + return item; +} + + +typedef struct { + sbuf_t *sp; + int num_items; + int id; +} producer_arg_t; + +typedef struct +{ + sbuf_t *sp; + int id; +} consumer_arg_t; + + +void *producer(void *arg) +{ + producer_arg_t *pa = (producer_arg_t *)arg; + for (int i = 0; i < pa->num_items; i++) + { + int val = rand() % 1000; + sbuf_insert(pa->sp,val); + sem_wait(&sum_mutex); + produced_sum += val; + sem_post(&sum_mutex); + printf("[Producer %d] produced %d\n",pa->id,val); + } + return NULL; +} + +void *consumer(void *arg) +{ + consumer_arg_t *ca = (consumer_arg_t *)arg; + while(1){ + int item = sbuf_remove(ca->sp); + if(item == POISON){ + sbuf_insert(ca->sp, POISON); + break; + } + sem_wait(&sum_mutex); + consumed_sum += item; + sem_post(&sum_mutex); + printf("[Consumer %d] consumed %d\n",ca->id,item); + } + + return NULL; +} + +int main(int argc, char *argv[]) +{ + if (argc != 4) + { + fprintf(stderr,"Usage: %s \n",argv[0]); + return 1; + } + + int k = atoi(argv[1]); + int m = atoi(argv[2]); + int N = atoi(argv[3]); + total_items = 0; + + srand(time(NULL)); + sem_init(&sum_mutex, 0, 1); + + sbuf_t buf; + sbuf_init(&buf,N); + + + pthread_t *producers = malloc(k*sizeof(pthread_t)); + pthread_t *consumers = malloc(m*sizeof(pthread_t)); + producer_arg_t *pargs = malloc(k*sizeof(producer_arg_t)); + consumer_arg_t *cargs = malloc(m*sizeof(consumer_arg_t)); + + for (int i = 0; i < k; i++) + { + pargs[i].sp = &buf; + pargs[i].num_items = rand() % 5 + 1; // 每个生产者产生1-10个随机数 + pargs[i].id = i + 1; + total_items += pargs[i].num_items; + pthread_create(&producers[i],NULL,producer,&pargs[i]); + } + + for (int i = 0; i < m; i++) + { + cargs[i].sp = &buf; + cargs[i].id = i + 1; + pthread_create(&consumers[i],NULL,consumer,&cargs[i]); + } + + for (int i = 0; i < k; i++) + { + pthread_join(producers[i],NULL); + } + + sbuf_insert(&buf, POISON); + + for (int i = 0; i < m; i++) + { + pthread_join(consumers[i],NULL); + } + + printf("\n=== Verifcation Results ===\n"); + printf("Produced sum: %lld\n", produced_sum); + printf("Consumed sum: %lld\n", consumed_sum); + if (produced_sum == consumed_sum) + { + printf("Verification successful: produced sum matches consumed sum.\n"); + } + else + { + printf("Verification failed: produced sum does not match consumed sum.\n"); + } + + free(producers); + free(consumers); + free(pargs); + free(cargs); + sbuf_deinit(&buf); + sem_destroy(&sum_mutex); + + return 0; +} \ No newline at end of file diff --git a/exp1/task64 b/exp1/task64 new file mode 100755 index 0000000..b500030 Binary files /dev/null and b/exp1/task64 differ diff --git a/exp1/task64.c b/exp1/task64.c new file mode 100644 index 0000000..03c405f --- /dev/null +++ b/exp1/task64.c @@ -0,0 +1,89 @@ +/*任务4(必做):编译、测试和运行示例程序psum64.c +1)测量线程数为1、2、4、8、16时程序的执行时间,计算加速比和效率,并做出解释。 +2)改写该程序psum64.c,保存为task64.c,实现计算02+12+… +(n-1)2功能。 +*/ + +#include +#include +#include +#include +#include + +#define MAXTHREADS 16 + +void *sum(void *vargp); +double get_time() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; +} + + +unsigned long long psum64[MAXTHREADS]; +unsigned long long nelems_per_thread; + +int main(int argc, char **argv) +{ + unsigned long long i,nelems,log_nelems,nthreads,result = 0; + pthread_t tid[MAXTHREADS]; + int myid[MAXTHREADS]; + + if(argc != 3) + { + printf("Usage: %s \n",argv[0]); + exit(0); + } + nthreads = atoi(argv[1]); + log_nelems = atoi(argv[2]); + nelems = (1LL << log_nelems); + nelems_per_thread = nelems / nthreads; + + double t_start = get_time(); + for ( i = 0; i < nthreads; i++) + { + myid[i] = i; + pthread_create(&tid[i],NULL,sum,&myid[i]); + } + + for ( i = 0; i < nthreads; i++) + { + pthread_join(tid[i],NULL); + } + + for ( i = 0; i < nthreads; i++) + { + result += psum64[i]; + } + + if (result == (nelems*(nelems-1)*(2*nelems-1))/6) + { + printf("Correct result: %llu\n",result); + } + else + { + printf("Wrong result: %llu\n",result); + } + double t_end = get_time(); + printf("Time taken: %f seconds\n", t_end - t_start); + + exit(0); +} + + + +void *sum(void *vargp) +{ + int myid = *((int *)vargp); + unsigned long long begin = myid * nelems_per_thread; + unsigned long long end = begin + nelems_per_thread; + unsigned long long i,lsum=0; + + for (i = begin; i < end; i++) + { + lsum += i * i; + } + + psum64[myid] = lsum; + return NULL; +} \ No newline at end of file