完成并修改正确必做题
This commit is contained in:
BIN
exp1/badcount
BIN
exp1/badcount
Binary file not shown.
59
exp1/badcount.c
Normal file
59
exp1/badcount.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
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 <niters>\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;
|
||||||
|
}
|
||||||
79
exp1/psum64.c
Normal file
79
exp1/psum64.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*任务4(必做):编译、测试和运行示例程序psum64.c
|
||||||
|
1)测量线程数为1、2、4、8、16时程序的执行时间,计算加速比和效率,并做出解释。
|
||||||
|
2)改写该程序psum64.c,保存为task64.c,实现计算02+12+… +(n-1)2功能。
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#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 <nthreads> <log_nelems>\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;
|
||||||
|
}
|
||||||
BIN
exp1/task61
BIN
exp1/task61
Binary file not shown.
@@ -31,7 +31,7 @@ void *wokerT3(void *vargp)
|
|||||||
for(int i=0; i<5; i++)
|
for(int i=0; i<5; i++)
|
||||||
{
|
{
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
printf("Current time %s\n",ctime(&t));
|
printf("Current time %s",ctime(&t));
|
||||||
int sleep_time = rand() % 5 + 1;
|
int sleep_time = rand() % 5 + 1;
|
||||||
sleep(sleep_time);
|
sleep(sleep_time);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
exp1/task62
Executable file
BIN
exp1/task62
Executable file
Binary file not shown.
@@ -5,33 +5,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
void *increase(void *vargp);
|
||||||
|
void *decrease(void *vargp);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
sem_t mutex;
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
unsigned int niters;
|
unsigned int niters;
|
||||||
@@ -45,8 +23,8 @@ int main(int argc, char **argv)
|
|||||||
niters = atoll(argv[1]);
|
niters = atoll(argv[1]);
|
||||||
|
|
||||||
sem_init(&mutex, 0, 1);
|
sem_init(&mutex, 0, 1);
|
||||||
pthread_create(&t1,NULL,increase,(void*)niters);
|
pthread_create(&t1,NULL,increase,(void *)niters);
|
||||||
pthread_create(&t2,NULL,decrease,(void*)niters);
|
pthread_create(&t2,NULL,decrease,(void *)niters);
|
||||||
pthread_join(t1,NULL);
|
pthread_join(t1,NULL);
|
||||||
pthread_join(t2,NULL);
|
pthread_join(t2,NULL);
|
||||||
|
|
||||||
@@ -61,3 +39,27 @@ int main(int argc, char **argv)
|
|||||||
sem_destroy(&mutex);
|
sem_destroy(&mutex);
|
||||||
exit(0);
|
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;
|
||||||
|
}
|
||||||
BIN
exp1/task63
Executable file
BIN
exp1/task63
Executable file
Binary file not shown.
185
exp1/task63.c
185
exp1/task63.c
@@ -1,3 +1,10 @@
|
|||||||
|
/*
|
||||||
|
编写一个多线程程序task63.c,创建k个生产者线程和m个消费者线程,
|
||||||
|
每个生产者线程产生若干个随机数,通过由N个单元构成的缓冲区,发送给消费者线程,
|
||||||
|
进行输出显示,产生Pthread信号量实现生产者/消费者线程间同步,并且设计一种方案对程序正确性进行验证。
|
||||||
|
提示:一种非严谨的简单验证方案是,将生产者线程产生的所有随机数相加得到一个和,消费者线程接收到的所有随机数相加得到另一个和,验证两个和是否一致来来验证程序正确性
|
||||||
|
|
||||||
|
*/
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -5,3 +12,181 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#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 <k_producers> <m_consumers> <N_buffer>\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;
|
||||||
|
}
|
||||||
BIN
exp1/task64
Executable file
BIN
exp1/task64
Executable file
Binary file not shown.
89
exp1/task64.c
Normal file
89
exp1/task64.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*任务4(必做):编译、测试和运行示例程序psum64.c
|
||||||
|
1)测量线程数为1、2、4、8、16时程序的执行时间,计算加速比和效率,并做出解释。
|
||||||
|
2)改写该程序psum64.c,保存为task64.c,实现计算02+12+… +(n-1)2功能。
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#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 <nthreads> <log_nelems>\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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user