This commit is contained in:
yly 2025-11-17 20:29:14 +08:00
commit a628d873c5
10 changed files with 462 additions and 0 deletions

19
lab1/Makefile Normal file
View File

@ -0,0 +1,19 @@
# Makefile for building mpi_hello_world from mpi_hello_world.c
MPICC ?= mpicc
MPIRUN ?= mpirun
CFLAGS ?= -O2 -Wall
TARGET := $(basename $(SRC))
SRC := mpi_hello_world.c serial_pi.c mpi_pi.c
.PHONY: all clean run
all: $(TARGET)
$(TARGET): $(SRC)
$(MPICC) $(CFLAGS) -o $@ $<
run: $(TARGET)
$(MPIRUN) -np 4 ./$@
clean:
rm -f $(TARGET)

97
lab1/do_lab.sh Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -euo pipefail
# cd to the directory where this script lives
cd "$(dirname "$0")"
echo "Running make..."
make
# detect MPI launcher
if command -v mpirun >/dev/null 2>&1; then
MPI_LAUNCHER=mpirun
MPI_FLAG="-np"
elif command -v mpiexec >/dev/null 2>&1; then
MPI_LAUNCHER=mpiexec
MPI_FLAG="-n"
else
echo "Error: neither mpirun nor mpiexec found in PATH." >&2
exit 2
fi
# detect number of processes (fallback to 4)
if command -v nproc >/dev/null 2>&1; then
NP=$(nproc)
elif [ -n "${NUMBER_OF_PROCESSORS-}" ]; then
NP=$NUMBER_OF_PROCESSORS
else
NP=4
fi
echo "Using $MPI_LAUNCHER $MPI_FLAG $NP"
# helper to measure elapsed "real" time (seconds) while also showing program output
measure_time() {
local label="$1"; shift
local -a cmd=("$@")
echo "---- Running: $label ----"
echo "Command: ${cmd[*]}"
local outfile timefile
outfile=$(mktemp)
timefile=$(mktemp)
if command -v /usr/bin/time >/dev/null 2>&1; then
# /usr/bin/time prints real time with %e (seconds) into timefile
/usr/bin/time -f "%e" -o "$timefile" "${cmd[@]}" 2>&1 | tee "$outfile"
elapsed=$(<"$timefile")
else
# bash builtin time: capture stderr (which receives the timing) and stdout separately
TIMEFORMAT='%R'
{ time "${cmd[@]}" 1> "$outfile"; } 2> "$timefile"
elapsed=$(<"$timefile")
# also print program output
cat "$outfile"
fi
rm -f "$outfile" "$timefile"
# normalize elapsed to a number (strip spaces)
echo "${elapsed//[[:space:]]/}"
}
# ensure executables exist
for exe in mpi_hello_world mpi_pi serial_pi; do
if [ ! -x "./$exe" ]; then
echo "Error: executable ./$exe not found or not executable. Did make build it?" >&2
exit 3
fi
done
# run mpi_hello_world (show output, don't measure for comparison)
echo "==> Executing mpi_hello_world"
"$MPI_LAUNCHER" "$MPI_FLAG" "$NP" ./mpi_hello_world
# measure mpi_pi
mpi_elapsed=$(measure_time "mpi_pi" "$MPI_LAUNCHER" "$MPI_FLAG" "$NP" ./mpi_pi)
# measure serial_pi
serial_elapsed=$(measure_time "serial_pi" ./serial_pi)
# compute comparison
# protect against zero
if awk "BEGIN{exit($mpi_elapsed <= 0)}"; then
echo "Error: measured mpi_pi time is zero or negative." >&2
exit 4
fi
speedup=$(awk -v s="$serial_elapsed" -v m="$mpi_elapsed" 'BEGIN{ if(m==0){print "inf"; exit} printf "%.3f", s/m }')
diff=$(awk -v s="$serial_elapsed" -v m="$mpi_elapsed" 'BEGIN{printf "%.3f", s-m }')
echo
echo "Summary:"
echo " mpi_pi time (s): $mpi_elapsed"
echo " serial_pi time (s): $serial_elapsed"
echo " Difference (serial - mpi) (s): $diff"
echo " Speedup (serial / mpi): $speedup x"
exit 0

29
lab1/mpi_hello_world.c Normal file
View File

@ -0,0 +1,29 @@
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment. The two arguments to MPI Init are not
// currently used by MPI implementations, but are there in case future
// implementations might need the arguments.
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n", processor_name, world_rank, world_size);
// Finalize the MPI environment. No more MPI calls can be made after this
MPI_Finalize();
}

54
lab1/mpi_pi.c Normal file
View File

@ -0,0 +1,54 @@
#include <stdio.h>
#include <math.h>
#include <mpi.h>
/* We define pi here so we can check and see how accurate our computation is. */
#define PI 3.141592653589793238462643
int main(int argc, char **argv) {
MPI_Init(&argc, &argv);
int processes, pe;
MPI_Comm_size(MPI_COMM_WORLD, &processes);
MPI_Comm_rank(MPI_COMM_WORLD, &pe);
/* Let's prompt for the number of intervals. We'll broadcast whatever
* process 0 reads to the other processes. We could use command line
* arguments instead, but then there'd be no reason to broadcast! */
int intervals;
if (pe == 0) {
printf("Number of intervals: ");
fflush(stdout);
scanf("%d", &intervals);
}
double time1 = MPI_Wtime();
MPI_Bcast(&intervals, 1, MPI_INT, 0, MPI_COMM_WORLD);
int count = intervals / processes;
int start = count * pe;
int end = count * pe + count;
int i;
double subtotal, total = 0;
for (i = start; i < end; ++i) {
subtotal += pow(-1, i) / (2 * i + 1);
}
MPI_Reduce(&subtotal, &total, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
double time2 = MPI_Wtime();
if (pe == 0) {
total = total * 4;
printf("Result: %.10lf\n", total);
printf("Accuracy: %.10lf\n", PI - total);
printf("Time: %.10lf\n", time2 - time1);
}
MPI_Finalize();
}

35
lab1/serial_pi.c Normal file
View File

@ -0,0 +1,35 @@
/*
* File: pi-c.c
* Purpose: Estimates pi using the Leibniz formula (in C).
* Compile: gcc -o pi-c pi-c.c -lm
* Run: ./pi-c
*/
#include <stdio.h>
#include <math.h>
#include <time.h>
/* We define pi here so we can check and see how accurate our computation is. */
#define PI 3.141592653589793238462643
int main(int argc, char **argv) {
int intervals;
printf("Number of intervals: ");
fflush(stdout);
scanf("%d", &intervals);
clock_t time1 = clock();
int i;
double sum, total = 0;
for (i = 0; i < intervals; ++i) {
total += pow(-1, i) / (2 * i + 1);
}
clock_t time2 = clock();
total = total * 4;
printf("Result: %.10lf\n", total);
printf("Accuracy: %.10lf\n", PI - total);
printf("Time:
%.10lf\n", (double)(time2 - time1)/CLOCKS_PER_SEC);
}

16
lab2/pthread/Makefile Normal file
View File

@ -0,0 +1,16 @@
CC = gcc
CFLAGS = -Wall -Wextra -O2
LDLIBS = -lpthread
SRCS := $(wildcard *.c)
BINS := $(SRCS:.c=)
.PHONY: all clean
all: $(BINS)
%: %.c
$(CC) $(CFLAGS) -o $@ $< $(LDLIBS)
clean:
-rm -f $(BINS) *.o

View File

@ -0,0 +1,73 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/time.h>
FILE *fd;
int TotalEvenWords = 0, TotalOddWords = 0, TotalWords = 0;
int GetNextLine(FILE *f, char *Line)
{
if (fgets(Line, 132, f)==NULL) if (feof(f))return EOF; else return 1;
}
int GetWordAndLetterCount(char *Line)
{
int Word_Count = 0, Letter_Count = 0;
for (int i=0;i<132;i++)
{
if ((Line[i]!=' ')&&(Line[i]!=0)&&(Line[i]!='\n')) Letter_Count++;
else {
if (Letter_Count % 2) {
TotalOddWords++;
Word_Count++;
Letter_Count = 0;
}
else {
TotalEvenWords++;
Word_Count++;
Letter_Count = 0;
}
if (Line[i]==0) break;
}
}
return (Word_Count);
// encode two return values
}
int CountWords()
{
bool bDone = false;
char inLine[132];
while (!bDone)
{
bDone = (GetNextLine(fd, inLine) == EOF);
if (!bDone){
TotalWords += GetWordAndLetterCount(inLine) ;
}
}
return 0;
}
int main()
{
fd = fopen("./InFile1.txt", "r"); // Open file for read
struct timeval TimeStampStart, TimeStampStop;
double ExeTime;
gettimeofday(&TimeStampStart, NULL);
CountWords();
gettimeofday(&TimeStampStop, NULL);
ExeTime = (double)(TimeStampStop.tv_sec - TimeStampStart.tv_sec) +
(double)(TimeStampStop.tv_usec - TimeStampStart.tv_usec) * 1e-6;
fclose(fd);
printf("Total Words = %8d\n", TotalWords);
printf("Total Even Words = %7d\nTotal Odd Words = %7d\n", TotalEvenWords, TotalOddWords);
printf("The time to count word was %f seconds\n", (ExeTime));
return 0;
}

View File

@ -0,0 +1,73 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/time.h>
FILE *fd;
int TotalEvenWords = 0, TotalOddWords = 0, TotalWords = 0;
int GetNextLine(FILE *f, char *Line)
{
if (fgets(Line, 132, f)==NULL) if (feof(f))return EOF; else return 1;
}
int GetWordAndLetterCount(char *Line)
{
int Word_Count = 0, Letter_Count = 0;
for (int i=0;i<132;i++)
{
if ((Line[i]!=' ')&&(Line[i]!=0)&&(Line[i]!='\n')) Letter_Count++;
else {
if (Letter_Count % 2) {
TotalOddWords++;
Word_Count++;
Letter_Count = 0;
}
else {
TotalEvenWords++;
Word_Count++;
Letter_Count = 0;
}
if (Line[i]==0) break;
}
}
return (Word_Count);
// encode two return values
}
int CountWords()
{
bool bDone = false;
char inLine[132];
while (!bDone)
{
bDone = (GetNextLine(fd, inLine) == EOF);
if (!bDone){
TotalWords += GetWordAndLetterCount(inLine) ;
}
}
return 0;
}
int main()
{
fd = fopen("./InFile1.txt", "r"); // Open file for read
struct timeval TimeStampStart, TimeStampStop;
double ExeTime;
gettimeofday(&TimeStampStart, NULL);
CountWords();
gettimeofday(&TimeStampStop, NULL);
ExeTime = (double)(TimeStampStop.tv_sec - TimeStampStart.tv_sec) +
(double)(TimeStampStop.tv_usec - TimeStampStart.tv_usec) * 1e-6;
fclose(fd);
printf("Total Words = %8d\n", TotalWords);
printf("Total Even Words = %7d\nTotal Odd Words = %7d\n", TotalEvenWords, TotalOddWords);
printf("The time to count word was %f seconds\n", (ExeTime));
return 0;
}

30
lab2/pthread/pi.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <sys/time.h>
long long num_steps = 1000000000;
double step;
int main(int argc, char* argv[])
{
struct timeval TimeStampStart, TimeStampStop;
double ExeTime;
double x, pi, sum=0.0;
int i;
step = 1./(double)num_steps;
gettimeofday(&TimeStampStart, NULL);
for (i=0; i<num_steps; i++)
{
x = (i + .5)*step;
sum = sum + 4.0/(1.+ x*x);
}
pi = sum*step;
gettimeofday(&TimeStampStop, NULL);
ExeTime = (double)(TimeStampStop.tv_sec - TimeStampStart.tv_sec) + (double)(TimeStampStop.tv_usec - TimeStampStart.tv_usec) * 1e-6;
printf("The value of PI is %15.12f\n",pi);
printf("The time to calculate PI was %f seconds\n", (ExeTime));
return 0;
}

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
const int NumThreads = 16;
static void* HelloFunc(void* pArg)
{
printf("Hello Thread %d !\n", *((int*)pArg));
}
int main()
{
int Num[NumThreads];
pthread_t ThreadIDs[NumThreads];
pthread_attr_t attr[NumThreads];
for (int i = 0; i < NumThreads; i++) {
Num[i] = i;
pthread_attr_init(&attr[i]);
pthread_attr_setdetachstate(&attr[i], PTHREAD_CREATE_JOINABLE);
}
for (int i = 0; i < NumThreads; i++) {
int err = pthread_create(&ThreadIDs[i], &attr[i], HelloFunc, (void*)&Num[i]);
if(err != 0) {
printf("ERROR: pthread_create() return code: %d\n", err);
}
}
for (int i = 0; i < NumThreads; i++) {
pthread_join(ThreadIDs[i], NULL);
printf("Thread %d end !\n", i);
}
return 0;
}