init
This commit is contained in:
commit
a628d873c5
19
lab1/Makefile
Normal file
19
lab1/Makefile
Normal 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
97
lab1/do_lab.sh
Normal 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
29
lab1/mpi_hello_world.c
Normal 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
54
lab1/mpi_pi.c
Normal 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
35
lab1/serial_pi.c
Normal 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
16
lab2/pthread/Makefile
Normal 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
|
||||||
73
lab2/pthread/count_words_par.c
Normal file
73
lab2/pthread/count_words_par.c
Normal 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;
|
||||||
|
}
|
||||||
73
lab2/pthread/count_words_ser.c
Normal file
73
lab2/pthread/count_words_ser.c
Normal 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
30
lab2/pthread/pi.c
Normal 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;
|
||||||
|
}
|
||||||
36
lab2/pthread/pthread_hello.c
Normal file
36
lab2/pthread/pthread_hello.c
Normal 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;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user