From a628d873c547cd997a3532a0978ed5c709423eaa Mon Sep 17 00:00:00 2001 From: yly Date: Mon, 17 Nov 2025 20:29:14 +0800 Subject: [PATCH] init --- lab1/Makefile | 19 +++++++ lab1/do_lab.sh | 97 ++++++++++++++++++++++++++++++++++ lab1/mpi_hello_world.c | 29 ++++++++++ lab1/mpi_pi.c | 54 +++++++++++++++++++ lab1/serial_pi.c | 35 ++++++++++++ lab2/pthread/Makefile | 16 ++++++ lab2/pthread/count_words_par.c | 73 +++++++++++++++++++++++++ lab2/pthread/count_words_ser.c | 73 +++++++++++++++++++++++++ lab2/pthread/pi.c | 30 +++++++++++ lab2/pthread/pthread_hello.c | 36 +++++++++++++ 10 files changed, 462 insertions(+) create mode 100644 lab1/Makefile create mode 100644 lab1/do_lab.sh create mode 100644 lab1/mpi_hello_world.c create mode 100644 lab1/mpi_pi.c create mode 100644 lab1/serial_pi.c create mode 100644 lab2/pthread/Makefile create mode 100644 lab2/pthread/count_words_par.c create mode 100644 lab2/pthread/count_words_ser.c create mode 100644 lab2/pthread/pi.c create mode 100644 lab2/pthread/pthread_hello.c diff --git a/lab1/Makefile b/lab1/Makefile new file mode 100644 index 0000000..71a169c --- /dev/null +++ b/lab1/Makefile @@ -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) diff --git a/lab1/do_lab.sh b/lab1/do_lab.sh new file mode 100644 index 0000000..de892a7 --- /dev/null +++ b/lab1/do_lab.sh @@ -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 \ No newline at end of file diff --git a/lab1/mpi_hello_world.c b/lab1/mpi_hello_world.c new file mode 100644 index 0000000..5bb717a --- /dev/null +++ b/lab1/mpi_hello_world.c @@ -0,0 +1,29 @@ +#include +#include + +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(); +} diff --git a/lab1/mpi_pi.c b/lab1/mpi_pi.c new file mode 100644 index 0000000..cca3308 --- /dev/null +++ b/lab1/mpi_pi.c @@ -0,0 +1,54 @@ +#include +#include +#include + +/* 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(); +} diff --git a/lab1/serial_pi.c b/lab1/serial_pi.c new file mode 100644 index 0000000..c86b2b0 --- /dev/null +++ b/lab1/serial_pi.c @@ -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 +#include +#include + +/* 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); +} diff --git a/lab2/pthread/Makefile b/lab2/pthread/Makefile new file mode 100644 index 0000000..9b60085 --- /dev/null +++ b/lab2/pthread/Makefile @@ -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 \ No newline at end of file diff --git a/lab2/pthread/count_words_par.c b/lab2/pthread/count_words_par.c new file mode 100644 index 0000000..c6247f6 --- /dev/null +++ b/lab2/pthread/count_words_par.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/lab2/pthread/count_words_ser.c b/lab2/pthread/count_words_ser.c new file mode 100644 index 0000000..c6247f6 --- /dev/null +++ b/lab2/pthread/count_words_ser.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/lab2/pthread/pi.c b/lab2/pthread/pi.c new file mode 100644 index 0000000..53171be --- /dev/null +++ b/lab2/pthread/pi.c @@ -0,0 +1,30 @@ +#include +#include +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 +#include +#include +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; +}