test
This commit is contained in:
28
.vscode/tasks.json
vendored
Normal file
28
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++: gcc 生成活动文件",
|
||||||
|
"command": "/usr/bin/gcc",
|
||||||
|
"args": [
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"-g",
|
||||||
|
"${file}",
|
||||||
|
"-o",
|
||||||
|
"${fileDirname}/${fileBasenameNoExtension}"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${fileDirname}"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"detail": "调试器生成的任务。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
||||||
7
exp1/.vscode/launch.json
vendored
Normal file
7
exp1/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": []
|
||||||
|
}
|
||||||
28
exp1/.vscode/tasks.json
vendored
Normal file
28
exp1/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++: gcc 生成活动文件",
|
||||||
|
"command": "/usr/bin/gcc",
|
||||||
|
"args": [
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"-g",
|
||||||
|
"${file}",
|
||||||
|
"-o",
|
||||||
|
"${fileDirname}/${fileBasenameNoExtension}"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${fileDirname}"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"detail": "调试器生成的任务。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
||||||
BIN
exp1/badcount
Executable file
BIN
exp1/badcount
Executable file
Binary file not shown.
62
exp1/badcount.c
Normal file
62
exp1/badcount.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
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 <niters>\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_join(t1,NULL);
|
||||||
|
pthread_join(t2,NULL);
|
||||||
|
|
||||||
|
if (cnt != 0)
|
||||||
|
{
|
||||||
|
printf("Error! cnt=%d\n", cnt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Correct! cnt=%d\n", cnt);
|
||||||
|
}
|
||||||
|
sem_destroy(&mutex);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
BIN
exp1/task61
Executable file
BIN
exp1/task61
Executable file
Binary file not shown.
53
exp1/task61.c
Normal file
53
exp1/task61.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void *wokerT1(void *vargp)
|
||||||
|
{
|
||||||
|
for(int i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
printf("My name is Lvjinzhong\n");
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wokerT2(void *vargp)
|
||||||
|
{
|
||||||
|
for(int i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
printf("My student number is 2024414290124\n");
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wokerT3(void *vargp)
|
||||||
|
{
|
||||||
|
for(int i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
time_t t = time(NULL);
|
||||||
|
printf("Current time %s\n",ctime(&t));
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pthread_t t1,t2,t3;
|
||||||
|
pthread_create(&t1, NULL, wokerT1, NULL);
|
||||||
|
pthread_create(&t2, NULL, wokerT2, NULL);
|
||||||
|
pthread_create(&t3, NULL, wokerT3, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
pthread_join(t1, NULL);
|
||||||
|
pthread_join(t2, NULL);
|
||||||
|
pthread_join(t3, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
吕锦中202441429012406/2024414290124-吕锦中-lab6.tar.gz
Normal file
BIN
吕锦中202441429012406/2024414290124-吕锦中-lab6.tar.gz
Normal file
Binary file not shown.
34
吕锦中202441429012406/badcount.c
Normal file
34
吕锦中202441429012406/badcount.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
volatile long long counter = 0;
|
||||||
|
long long niters;
|
||||||
|
|
||||||
|
void *thread_func(void *arg) {
|
||||||
|
for (long long i = 0; i < niters; i++) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <niters>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
niters = atoll(argv[1]);
|
||||||
|
|
||||||
|
pthread_t t1, t2;
|
||||||
|
pthread_create(&t1, NULL, thread_func, NULL);
|
||||||
|
pthread_create(&t2, NULL, thread_func, NULL);
|
||||||
|
|
||||||
|
pthread_join(t1, NULL);
|
||||||
|
pthread_join(t2, NULL);
|
||||||
|
|
||||||
|
printf("Expected: %lld, Got: %lld\n", 2 * niters, counter);
|
||||||
|
if (counter != 2 * niters) {
|
||||||
|
printf("ERROR: Race condition detected!\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
145
吕锦中202441429012406/matmult.c
Normal file
145
吕锦中202441429012406/matmult.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_THREADS 64
|
||||||
|
|
||||||
|
int N;
|
||||||
|
double **A, **B, **C_parallel, **C_serial;
|
||||||
|
int nthreads;
|
||||||
|
int rows_per_thread;
|
||||||
|
|
||||||
|
void **allocate_matrix(int n) {
|
||||||
|
double **mat = (double **)malloc(n * sizeof(double *));
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
mat[i] = (double *)malloc(n * sizeof(double));
|
||||||
|
}
|
||||||
|
return (void **)mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_matrix(double **mat, int n) {
|
||||||
|
for (int i = 0; i < n; i++) free(mat[i]);
|
||||||
|
free(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_matrix(double **mat, int n) {
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
for (int j = 0; j < n; j++)
|
||||||
|
mat[i][j] = (double)(rand() % 100) / 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *multiply_thread(void *arg) {
|
||||||
|
int start_row = *(int *)arg;
|
||||||
|
int end_row = start_row + rows_per_thread;
|
||||||
|
if (end_row > N) end_row = N;
|
||||||
|
|
||||||
|
for (int i = start_row; i < end_row; i++) {
|
||||||
|
for (int j = 0; j < N; j++) {
|
||||||
|
double sum = 0.0;
|
||||||
|
for (int k = 0; k < N; k++) {
|
||||||
|
sum += A[i][k] * B[k][j];
|
||||||
|
}
|
||||||
|
C_parallel[i][j] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_multiply() {
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
for (int j = 0; j < N; j++) {
|
||||||
|
double sum = 0.0;
|
||||||
|
for (int k = 0; k < N; k++) {
|
||||||
|
sum += A[i][k] * B[k][j];
|
||||||
|
}
|
||||||
|
C_serial[i][j] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_time() {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify() {
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
for (int j = 0; j < N; j++) {
|
||||||
|
if (C_parallel[i][j] - C_serial[i][j] > 0.001 ||
|
||||||
|
C_serial[i][j] - C_parallel[i][j] > 0.001) {
|
||||||
|
printf("Mismatch at [%d][%d]: parallel=%.6f, serial=%.6f\n",
|
||||||
|
i, j, C_parallel[i][j], C_serial[i][j]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "Usage: %s <N> <num_threads>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
N = atoi(argv[1]);
|
||||||
|
nthreads = atoi(argv[2]);
|
||||||
|
if (nthreads > MAX_THREADS) nthreads = MAX_THREADS;
|
||||||
|
if (nthreads > N) nthreads = N;
|
||||||
|
|
||||||
|
rows_per_thread = N / nthreads;
|
||||||
|
|
||||||
|
srand(42);
|
||||||
|
|
||||||
|
A = (double **)allocate_matrix(N);
|
||||||
|
B = (double **)allocate_matrix(N);
|
||||||
|
C_parallel = (double **)allocate_matrix(N);
|
||||||
|
C_serial = (double **)allocate_matrix(N);
|
||||||
|
|
||||||
|
init_matrix(A, N);
|
||||||
|
init_matrix(B, N);
|
||||||
|
|
||||||
|
pthread_t threads[MAX_THREADS];
|
||||||
|
int starts[MAX_THREADS];
|
||||||
|
|
||||||
|
double t_start = get_time();
|
||||||
|
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
starts[i] = i * rows_per_thread;
|
||||||
|
pthread_create(&threads[i], NULL, multiply_thread, &starts[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t_end = get_time();
|
||||||
|
double t_parallel = t_end - t_start;
|
||||||
|
|
||||||
|
/* Serial version for verification */
|
||||||
|
t_start = get_time();
|
||||||
|
serial_multiply();
|
||||||
|
t_end = get_time();
|
||||||
|
double t_serial = t_end - t_start;
|
||||||
|
|
||||||
|
printf("Matrix size: %d x %d, Threads: %d\n", N, N, nthreads);
|
||||||
|
printf("Parallel time: %.6f s\n", t_parallel);
|
||||||
|
printf("Serial time: %.6f s\n", t_serial);
|
||||||
|
printf("Speedup: %.4f\n", t_serial / t_parallel);
|
||||||
|
printf("Efficiency: %.4f\n", t_serial / t_parallel / nthreads);
|
||||||
|
|
||||||
|
if (verify()) {
|
||||||
|
printf("Verification: SUCCESS\n");
|
||||||
|
} else {
|
||||||
|
printf("Verification: FAILED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free_matrix(A, N);
|
||||||
|
free_matrix(B, N);
|
||||||
|
free_matrix(C_parallel, N);
|
||||||
|
free_matrix(C_serial, N);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
66
吕锦中202441429012406/psum64.c
Normal file
66
吕锦中202441429012406/psum64.c
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define MAX_THREADS 64
|
||||||
|
#define N 1000000000LL
|
||||||
|
|
||||||
|
long long global_sum = 0;
|
||||||
|
long long nelems_per_thread;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
void *sum_thread(void *arg) {
|
||||||
|
long long start = *(long long *)arg;
|
||||||
|
long long local_sum = 0;
|
||||||
|
long long end = start + nelems_per_thread;
|
||||||
|
if (end > N) end = N;
|
||||||
|
for (long long i = start; i < end; i++) {
|
||||||
|
local_sum += i;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
global_sum += local_sum;
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_time() {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <num_threads>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nthreads = atoi(argv[1]);
|
||||||
|
if (nthreads > MAX_THREADS) nthreads = MAX_THREADS;
|
||||||
|
|
||||||
|
nelems_per_thread = N / nthreads;
|
||||||
|
pthread_mutex_init(&mutex, NULL);
|
||||||
|
|
||||||
|
pthread_t threads[MAX_THREADS];
|
||||||
|
long long starts[MAX_THREADS];
|
||||||
|
|
||||||
|
double t_start = get_time();
|
||||||
|
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
starts[i] = i * nelems_per_thread;
|
||||||
|
pthread_create(&threads[i], NULL, sum_thread, &starts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t_end = get_time();
|
||||||
|
double elapsed = t_end - t_start;
|
||||||
|
|
||||||
|
printf("Threads: %d, Sum: %lld, Time: %.6f s\n", nthreads, global_sum, elapsed);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
58
吕锦中202441429012406/task61.c
Normal file
58
吕锦中202441429012406/task61.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void *thread_T1(void *arg) {
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
printf("My name is 吕锦中\n");
|
||||||
|
if (i < 5) {
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thread_T2(void *arg) {
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
printf("My student number is 2024414290124\n");
|
||||||
|
if (i < 5) {
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *thread_T3(void *arg) {
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm *tm_info = localtime(&now);
|
||||||
|
char time_str[64];
|
||||||
|
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
|
||||||
|
printf("Current time %s\n", time_str);
|
||||||
|
if (i < 5) {
|
||||||
|
int sleep_time = rand() % 5 + 1;
|
||||||
|
sleep(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
srand(time(NULL));
|
||||||
|
pthread_t t1, t2, t3;
|
||||||
|
|
||||||
|
pthread_create(&t1, NULL, thread_T1, NULL);
|
||||||
|
pthread_create(&t2, NULL, thread_T2, NULL);
|
||||||
|
pthread_create(&t3, NULL, thread_T3, NULL);
|
||||||
|
|
||||||
|
pthread_join(t1, NULL);
|
||||||
|
pthread_join(t2, NULL);
|
||||||
|
pthread_join(t3, NULL);
|
||||||
|
|
||||||
|
printf("All threads finished.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
44
吕锦中202441429012406/task62.c
Normal file
44
吕锦中202441429012406/task62.c
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
long long counter = 0;
|
||||||
|
long long niters;
|
||||||
|
sem_t mutex;
|
||||||
|
|
||||||
|
void *thread_func(void *arg) {
|
||||||
|
for (long long i = 0; i < niters; i++) {
|
||||||
|
sem_wait(&mutex);
|
||||||
|
counter++;
|
||||||
|
sem_post(&mutex);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <niters>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
niters = atoll(argv[1]);
|
||||||
|
|
||||||
|
sem_init(&mutex, 0, 1);
|
||||||
|
|
||||||
|
pthread_t t1, t2;
|
||||||
|
pthread_create(&t1, NULL, thread_func, NULL);
|
||||||
|
pthread_create(&t2, NULL, thread_func, NULL);
|
||||||
|
|
||||||
|
pthread_join(t1, NULL);
|
||||||
|
pthread_join(t2, NULL);
|
||||||
|
|
||||||
|
sem_destroy(&mutex);
|
||||||
|
|
||||||
|
printf("Expected: %lld, Got: %lld\n", 2 * niters, counter);
|
||||||
|
if (counter == 2 * niters) {
|
||||||
|
printf("SUCCESS: No race condition.\n");
|
||||||
|
} else {
|
||||||
|
printf("ERROR: Race condition detected!\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
176
吕锦中202441429012406/task63.c
Normal file
176
吕锦中202441429012406/task63.c
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define POISON -1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int *buf;
|
||||||
|
int n;
|
||||||
|
int outpos;
|
||||||
|
int inpos;
|
||||||
|
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 consumed_count = 0;
|
||||||
|
int total_items;
|
||||||
|
sem_t count_mutex;
|
||||||
|
|
||||||
|
void sbuf_init(sbuf_t *sp, int n) {
|
||||||
|
sp->buf = (int *)malloc(n * sizeof(int));
|
||||||
|
sp->n = n;
|
||||||
|
sp->outpos = 0;
|
||||||
|
sp->inpos = 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) {
|
||||||
|
/* Put poison back for other consumers, then exit */
|
||||||
|
sbuf_insert(ca->sp, POISON);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sem_wait(&sum_mutex);
|
||||||
|
consumed_sum += item;
|
||||||
|
sem_post(&sum_mutex);
|
||||||
|
sem_wait(&count_mutex);
|
||||||
|
consumed_count++;
|
||||||
|
sem_post(&count_mutex);
|
||||||
|
printf("[Consumer %d] consumed %d\n", ca->id, item);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 5) {
|
||||||
|
fprintf(stderr, "Usage: %s <k_producers> <items_per_producer> <m_consumers> <N_buffer>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k = atoi(argv[1]);
|
||||||
|
int items_per_producer = atoi(argv[2]);
|
||||||
|
int m = atoi(argv[3]);
|
||||||
|
int N = atoi(argv[4]);
|
||||||
|
total_items = k * items_per_producer;
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
sem_init(&sum_mutex, 0, 1);
|
||||||
|
sem_init(&count_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 = items_per_producer;
|
||||||
|
pargs[i].id = i + 1;
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for all producers to finish */
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
pthread_join(producers[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert one poison pill to start the termination chain */
|
||||||
|
sbuf_insert(&buf, POISON);
|
||||||
|
|
||||||
|
/* Wait for all consumers to finish */
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
pthread_join(consumers[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n=== Verification ===\n");
|
||||||
|
printf("Produced sum : %lld\n", produced_sum);
|
||||||
|
printf("Consumed sum : %lld\n", consumed_sum);
|
||||||
|
if (produced_sum == consumed_sum) {
|
||||||
|
printf("SUCCESS: Sums match! Program is correct.\n");
|
||||||
|
} else {
|
||||||
|
printf("ERROR: Sum mismatch! Difference = %lld\n",
|
||||||
|
produced_sum - consumed_sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(producers);
|
||||||
|
free(consumers);
|
||||||
|
free(pargs);
|
||||||
|
free(cargs);
|
||||||
|
sbuf_deinit(&buf);
|
||||||
|
sem_destroy(&sum_mutex);
|
||||||
|
sem_destroy(&count_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
70
吕锦中202441429012406/task64.c
Normal file
70
吕锦中202441429012406/task64.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define MAX_THREADS 64
|
||||||
|
#define N 1000000000LL
|
||||||
|
|
||||||
|
long long global_sum = 0;
|
||||||
|
long long nelems_per_thread;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
void *sum_squares_thread(void *arg) {
|
||||||
|
long long start = *(long long *)arg;
|
||||||
|
long long end = start + nelems_per_thread;
|
||||||
|
if (end > N) end = N;
|
||||||
|
long long local_sum = 0;
|
||||||
|
for (long long i = start; i < end; i++) {
|
||||||
|
local_sum += i * i;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
global_sum += local_sum;
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_time() {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <num_threads>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nthreads = atoi(argv[1]);
|
||||||
|
if (nthreads > MAX_THREADS) nthreads = MAX_THREADS;
|
||||||
|
|
||||||
|
nelems_per_thread = N / nthreads;
|
||||||
|
pthread_mutex_init(&mutex, NULL);
|
||||||
|
|
||||||
|
pthread_t threads[MAX_THREADS];
|
||||||
|
long long starts[MAX_THREADS];
|
||||||
|
|
||||||
|
double t_start = get_time();
|
||||||
|
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
starts[i] = i * nelems_per_thread;
|
||||||
|
pthread_create(&threads[i], NULL, sum_squares_thread, &starts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nthreads; i++) {
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t_end = get_time();
|
||||||
|
double elapsed = t_end - t_start;
|
||||||
|
|
||||||
|
/* Expected sum of squares: (n-1)*n*(2n-1)/6 */
|
||||||
|
long long expected = (N - 1) * N * (2 * N - 1) / 6;
|
||||||
|
printf("Threads: %d, Sum of squares: %lld, Expected: %lld, Time: %.6f s\n",
|
||||||
|
nthreads, global_sum, expected, elapsed);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
59
吕锦中202441429012406/task66.c
Normal file
59
吕锦中202441429012406/task66.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#define ITERATIONS 10000
|
||||||
|
|
||||||
|
double get_time() {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dummy_thread(void *arg) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
double t_start, t_end;
|
||||||
|
double fork_total = 0, pthread_total = 0;
|
||||||
|
|
||||||
|
/* Measure fork() */
|
||||||
|
t_start = get_time();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
_exit(0);
|
||||||
|
} else if (pid > 0) {
|
||||||
|
waitpid(pid, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t_end = get_time();
|
||||||
|
fork_total = t_end - t_start;
|
||||||
|
|
||||||
|
/* Measure pthread_create() */
|
||||||
|
t_start = get_time();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_create(&tid, NULL, dummy_thread, NULL);
|
||||||
|
pthread_join(tid, NULL);
|
||||||
|
}
|
||||||
|
t_end = get_time();
|
||||||
|
pthread_total = t_end - t_start;
|
||||||
|
|
||||||
|
printf("=== Performance Comparison ===\n");
|
||||||
|
printf("Iterations: %d\n", ITERATIONS);
|
||||||
|
printf("fork() total time: %.6f s (avg: %.3f us)\n",
|
||||||
|
fork_total, fork_total / ITERATIONS * 1000000);
|
||||||
|
printf("pthread_create() total time: %.6f s (avg: %.3f us)\n",
|
||||||
|
pthread_total, pthread_total / ITERATIONS * 1000000);
|
||||||
|
printf("Ratio (fork/pthread): %.2fx\n", fork_total / pthread_total);
|
||||||
|
printf("\nExplanation: fork() creates a new process with a copy of the\n");
|
||||||
|
printf("entire address space, which is much heavier than pthread_create()\n");
|
||||||
|
printf("which only creates a new thread sharing the same address space.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
177
吕锦中202441429012406/task67.c
Normal file
177
吕锦中202441429012406/task67.c
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int *buf;
|
||||||
|
int n;
|
||||||
|
int outpos;
|
||||||
|
int inpos;
|
||||||
|
sem_t mutex;
|
||||||
|
sem_t slots;
|
||||||
|
sem_t items;
|
||||||
|
} sbuf_t;
|
||||||
|
|
||||||
|
int num_workers = 5;
|
||||||
|
int target_workers = 5;
|
||||||
|
pthread_mutex_t worker_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_t *workers = NULL;
|
||||||
|
sbuf_t *sbuf_ptr = NULL;
|
||||||
|
volatile int running = 1;
|
||||||
|
|
||||||
|
void sbuf_init(sbuf_t *sp, int n) {
|
||||||
|
sp->buf = (int *)malloc(n * sizeof(int));
|
||||||
|
sp->n = n;
|
||||||
|
sp->outpos = 0;
|
||||||
|
sp->inpos = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *worker_thread(void *arg) {
|
||||||
|
int id = *(int *)arg;
|
||||||
|
free(arg);
|
||||||
|
sbuf_t *sp = sbuf_ptr;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
int seconds = sbuf_remove(sp);
|
||||||
|
if (seconds == -1) break;
|
||||||
|
printf("[Worker %d] executing task: sleep %d seconds\n", id, seconds);
|
||||||
|
sleep(seconds);
|
||||||
|
printf("[Worker %d] task completed\n", id);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjust_workers() {
|
||||||
|
pthread_mutex_lock(&worker_mutex);
|
||||||
|
int current = num_workers;
|
||||||
|
int target = target_workers;
|
||||||
|
|
||||||
|
if (target > current) {
|
||||||
|
/* Increase workers */
|
||||||
|
workers = realloc(workers, target * sizeof(pthread_t));
|
||||||
|
for (int i = current; i < target; i++) {
|
||||||
|
int *id = malloc(sizeof(int));
|
||||||
|
*id = i + 1;
|
||||||
|
pthread_create(&workers[i], NULL, worker_thread, id);
|
||||||
|
}
|
||||||
|
num_workers = target;
|
||||||
|
} else if (target < current) {
|
||||||
|
/* Decrease workers - insert poison pills */
|
||||||
|
int to_remove = current - target;
|
||||||
|
for (int i = 0; i < to_remove; i++) {
|
||||||
|
sbuf_insert(sbuf_ptr, -1);
|
||||||
|
}
|
||||||
|
for (int i = target; i < current; i++) {
|
||||||
|
pthread_join(workers[i], NULL);
|
||||||
|
}
|
||||||
|
num_workers = target;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&worker_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <buffer_size>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buf_size = atoi(argv[1]);
|
||||||
|
sbuf_t buf;
|
||||||
|
sbuf_ptr = &buf;
|
||||||
|
sbuf_init(&buf, buf_size);
|
||||||
|
|
||||||
|
/* Create initial 5 workers */
|
||||||
|
workers = malloc(5 * sizeof(pthread_t));
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
int *id = malloc(sizeof(int));
|
||||||
|
*id = i + 1;
|
||||||
|
pthread_create(&workers[i], NULL, worker_thread, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("=== Dynamic Thread Pool ===\n");
|
||||||
|
printf("Commands:\n");
|
||||||
|
printf(" <task_count> <seconds> - Add tasks\n");
|
||||||
|
printf(" quit - Exit\n");
|
||||||
|
printf("Initial workers: %d, Buffer size: %d\n\n", num_workers, buf_size);
|
||||||
|
|
||||||
|
char line[256];
|
||||||
|
while (1) {
|
||||||
|
printf("> ");
|
||||||
|
fflush(stdout);
|
||||||
|
if (!fgets(line, sizeof(line), stdin)) break;
|
||||||
|
|
||||||
|
if (strncmp(line, "quit", 4) == 0) break;
|
||||||
|
|
||||||
|
int task_count, seconds;
|
||||||
|
if (sscanf(line, "%d %d", &task_count, &seconds) == 2) {
|
||||||
|
printf("Adding %d tasks, each %d seconds...\n", task_count, seconds);
|
||||||
|
|
||||||
|
for (int i = 0; i < task_count; i++) {
|
||||||
|
/* Check if buffer is full - double workers */
|
||||||
|
int slots_avail;
|
||||||
|
sem_getvalue(&buf.slots, &slots_avail);
|
||||||
|
if (slots_avail == 0) {
|
||||||
|
target_workers = num_workers * 2;
|
||||||
|
printf("Buffer full, doubling workers to %d\n", target_workers);
|
||||||
|
adjust_workers();
|
||||||
|
}
|
||||||
|
|
||||||
|
sbuf_insert(&buf, seconds);
|
||||||
|
|
||||||
|
/* Check if buffer is empty - halve workers */
|
||||||
|
int items_avail;
|
||||||
|
sem_getvalue(&buf.items, &items_avail);
|
||||||
|
if (items_avail == 0 && num_workers > 2) {
|
||||||
|
target_workers = num_workers / 2;
|
||||||
|
if (target_workers < 2) target_workers = 2;
|
||||||
|
printf("Buffer empty, halving workers to %d\n", target_workers);
|
||||||
|
adjust_workers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Invalid command. Usage: <task_count> <seconds>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shutdown */
|
||||||
|
running = 0;
|
||||||
|
target_workers = 0;
|
||||||
|
adjust_workers();
|
||||||
|
|
||||||
|
sbuf_deinit(&buf);
|
||||||
|
free(workers);
|
||||||
|
printf("Done.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user