Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
cs241svngrader committed Sep 22, 2016
1 parent cb7d917 commit e4f9c37
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 0 deletions.
64 changes: 64 additions & 0 deletions teaching_threads/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
OBJS_DIR = .objs

# define all of student executables
EXE_PAR_MAP=par_map
EXES_STUDENT=$(EXE_PAR_MAP)

# list object file dependencies for each
OBJS_PAR_MAP=main.o map.o mappers.o par_map.o

# set up compiler
CC = clang
WARNINGS = -Wall -Wextra -Werror -Wno-error=unused-parameter
INCLUDES=-I./includes/
CFLAGS_DEBUG = $(INCLUDES) -O0 $(WARNINGS) -g -std=c99 -c -MMD -MP -D_GNU_SOURCE -DDEBUG
CFLAGS_RELEASE = $(INCLUDES) -O2 $(WARNINGS) -g -std=c99 -c -MMD -MP -D_GNU_SOURCE

# set up linker
LD = clang
LDFLAGS = -lrt -pthread

# the string in grep must appear in the hostname, otherwise the Makefile will
# not allow the assignment to compile
IS_VM=$(shell hostname | grep "fa16")

ifeq ($(IS_VM),)
$(error This assignment must be compiled on the CS241 VMs)
endif

.PHONY: all
all: release

# build types
.PHONY: release
.PHONY: debug

release: $(EXES_STUDENT)
debug: clean $(EXES_STUDENT:%=%-debug)

# include dependencies
-include $(OBJS_DIR)/*.d

$(OBJS_DIR):
@mkdir -p $(OBJS_DIR)

# patterns to create objects
# keep the debug and release postfix for object files so that we can always
# separate them correctly
$(OBJS_DIR)/%-debug.o: %.c | $(OBJS_DIR)
$(CC) $(CFLAGS_DEBUG) $< -o $@

$(OBJS_DIR)/%-release.o: %.c | $(OBJS_DIR)
$(CC) $(CFLAGS_RELEASE) $< -o $@

# exes
# you will need a pair of exe and exe-debug targets for each exe
$(EXE_PAR_MAP)-debug: $(OBJS_PAR_MAP:%.o=$(OBJS_DIR)/%-debug.o)
$(LD) $^ $(LDFLAGS) -o $@

$(EXE_PAR_MAP): $(OBJS_PAR_MAP:%.o=$(OBJS_DIR)/%-release.o)
$(LD) $^ $(LDFLAGS) -o $@

.PHONY: clean
clean:
rm -rf .objs $(EXES_STUDENT) $(EXES_STUDENT:%=%-debug)
107 changes: 107 additions & 0 deletions teaching_threads/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "map.h"
#include "mappers.h"
#include "par_map.h"

#define SEED 241

void validate_args(int argc, char *argv[]) {
// Verify correct number of arguments:
if (argc != 4) {
fprintf(stderr, "usage: %s <mapper_name> <list_len> <num_threads>\n",
argv[0]);
exit(1);
}

// Verifying that list_len and num_threads are actually integers greater than
// 1:
char *endptr;
for (int i = 2; i <= 3; i++) {
char *str_value = argv[i];
long value = strtol(str_value, &endptr, 10);

if (*endptr != '\0') {
fprintf(stderr, "Failed to convert an [%s] to a long!\n", str_value);
exit(3);
}

if (value < 1) {
fprintf(stderr, "[%s] needs to be greater than or equal to 1!\n",
str_value);
exit(4);
}
}
}

double *gen_random_list(size_t num_elems) {
double *list = (double *)malloc(sizeof(double) * num_elems);

for (size_t i = 0; i < num_elems; ++i) {
list[i] = ((double)rand() / (double)RAND_MAX);
}

return list;
}

bool verify(double *output_list, double *input_list, mapper map_func,
size_t list_len) {
// call on 'map_func' to modify 'list' inplace
// then verify element wise with 'output_list'.
double *soln_list = map(input_list, list_len, map_func);
for (size_t i = 0; i < list_len; ++i) {
if (soln_list[i] != output_list[i]) {
return false;
}
}
free(output_list);
free(soln_list);
return true;
}

int main(int argc, char *argv[]) {
validate_args(argc, argv);

// Seeding random number generator
srand(SEED);

char *mapper_name = argv[1];
size_t list_len = strtol(argv[2], NULL, 10);
size_t num_threads = strtol(argv[3], NULL, 10);

double *list = gen_random_list(list_len);
mapper map_func = get_mapper(mapper_name);

double *list_copy = (double *)malloc(sizeof(double) * list_len);
memcpy(list_copy, list, sizeof(double) * list_len);

struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);

double *ret_list = par_map(list_copy, list_len, map_func, num_threads);

clock_gettime(CLOCK_MONOTONIC, &end);
double diff =
(end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1E9;
printf("par_map ran in %f seconds\n", diff);

bool passed = verify(ret_list, list_copy, map_func, list_len);
if (passed) {
printf("Congratulations you have succesfully ran par_map with %s on a list "
"with %zu elements, and %zu threads\n",
mapper_name, list_len, num_threads);
}

free(list);
free(list_copy);
return passed;
}
16 changes: 16 additions & 0 deletions teaching_threads/map.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#include "map.h"
#include <stdlib.h>

double *map(double *list, size_t length, mapper map_func) {
double *ret_list = (double *)malloc(sizeof(double) * length);

for (size_t i = 0; i < length; ++i) {
ret_list[i] = map_func(list[i]);
}

return ret_list;
}
25 changes: 25 additions & 0 deletions teaching_threads/map.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#ifndef __CS241_MAP_H__
#define __CS241_MAP_H__

#include "mappers.h"
#include <stdlib.h>

/**
* Single threaded solution to map().
*
* This method takes in a `list` of doubles and returns a list of doubles where
* every element has had `map_func` applied to it.
*
* Note: that this function DOES NOT modify the original list.
*
* `list`- is a pointer to the begining of an array of doubles.
* `length` - is how many doubles are in the array of doubles.
* `map_func` - is the mapper used to transform a double to another double and
* is applied to every element of the list.
*/
double *map(double *list, size_t length, mapper map_func);
#endif /* __CS241_MAP_H__ */
34 changes: 34 additions & 0 deletions teaching_threads/mappers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "mappers.h"

mapper get_mapper(char *mapper_name) {
if (strcmp(mapper_name, "triple") == 0) {
return triple;
} else if (strcmp(mapper_name, "negate") == 0) {
return negate;
} else if (strcmp(mapper_name, "slow") == 0) {
return slow;
}
/* more else if clauses */
else /* default: */ {
fprintf(stderr, "Could not recognize [%s] as a mapper!\n", mapper_name);
exit(4);
}
}

double triple(double elem) { return 3 * elem; }

double negate(double elem) { return -1 * elem; }

double slow(double elem) {
usleep(1000);
return elem;
}
21 changes: 21 additions & 0 deletions teaching_threads/mappers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#ifndef __CS241_MAPPERS_H__
#define __CS241_MAPPERS_H__
/**
* This callback function takes in a double and returns a double.
*/
typedef double (*mapper)(double elem);

/**
* Returns the mapper that matches the name 'mapper_name'
*/
mapper get_mapper(char *mapper_name);

// Callback functions
double triple(double elem);
double negate(double elem);
double slow(double elem);
#endif /* __CS241_MAPPERS_H__ */
23 changes: 23 additions & 0 deletions teaching_threads/par_map.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "map.h"
#include "mappers.h"

/* You should create a struct that will get passed in by reference to your
* start_routine. */

/* You should create a start routine for your threads. */

double *par_map(double *list, size_t list_len, mapper map_func,
size_t num_threads) {
/* Your implementation goes here */
return NULL;
}
28 changes: 28 additions & 0 deletions teaching_threads/par_map.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Parallel Map Lab
* CS 241 - Fall 2016
*/
#ifndef __CS241_PAR_MAP_H__
#define __CS241_PAR_MAP_H__

#include "mappers.h"

/**
* multi-threaded solution to map().
*
* This method takes in a `list` of doubles and returns a list of doubles where
* every element has had `map_func` applied to it, but does so with
* `num_threads` threads.
*
* Note: that this function DOES NOT modify the original list.
*
* `list`- is a pointer to the begining of an array of doubles.
* `length` - is how many doubles are in the array of doubles.
* `map_func` - is the mapper used to transform a double to another double and
* is applied to every element of the list.
* `num_threads` - is how many threads (in addition to the main thread) are used
* in the parallelization.
*/
double *par_map(double *list, size_t length, mapper map_func,
size_t num_threads);
#endif /* __CS241_PAR_MAP_H__ */

0 comments on commit e4f9c37

Please sign in to comment.