From: Sam Moore Date: Tue, 11 Sep 2012 13:36:02 +0000 (+0800) Subject: Parallel Programming - Stuff happened X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;ds=sidebyside;h=46fe12165ce898eb47d2a2b9ce9945dbd65987a6;p=matches%2Fhonours.git Parallel Programming - Stuff happened I'm not sure what. The new version of pthread (with threads that don't exit) is not as much faster than the old version as I thought it would be. Sleep(10); Sam --- diff --git a/course/semester2/pprog/assignment1/Makefile b/course/semester2/pprog/assignment1/Makefile index e93e59df..c66787ed 100644 --- a/course/semester2/pprog/assignment1/Makefile +++ b/course/semester2/pprog/assignment1/Makefile @@ -1,6 +1,6 @@ # Makefile to build all programs -all : single-thread/nbody mthread/nbody +all : single-thread/nbody mthread/nbody openmp/nbody single-thread/nbody : make -C single-thread diff --git a/course/semester2/pprog/assignment1/get_data.py b/course/semester2/pprog/assignment1/get_data.py index 8ef82410..04ad2bec 100755 --- a/course/semester2/pprog/assignment1/get_data.py +++ b/course/semester2/pprog/assignment1/get_data.py @@ -12,10 +12,13 @@ import Gnuplot, Gnuplot.funcutils plot = Gnuplot.Gnuplot(persist=0) programs = { - "single-thread" : "./single-thread/nbody -g -v 5" + "single-thread" : "./single-thread/nbody -v 5" } -for n in range(1, 5): - programs.update({"mthread"+str(n) : "./mthread/nbody -g -v 5 -n "+str(n)}) +for n in range(2, 6): + programs.update({"mthread"+str(n) : "./mthread/nbody -v 5 --pedantic-graphics -n "+str(n)}) + programs.update({"mthread"+str(n) : "./mthread/nbody -v 5 -n "+str(n)}) + #programs.update({"slow-mthread"+str(n) : "./mthread/nbody-slow --pedantic-graphics -v 5 -n "+str(n)}) + #programs.update({"openmp"+str(n) : "./openmp/nbody -v 5 --pedantic-graphics -n " +str(n)}) @@ -29,8 +32,8 @@ def RunProgram(string): def RunForSteps(program, field, steps): results = [] - #print(str(program) + " -s "+str(steps) + " " + str(field)) - results.append(RunProgram(str(program) + " -s "+str(steps) + " " + str(field))) + print(str(program) + " -s "+str(steps) + " " + str(field)) + results = RunProgram(str(program) + " -s "+str(steps) + " " + str(field)) return results def VaryField(program, steps, fields): @@ -56,12 +59,18 @@ def main(argv): fields = map(int, os.listdir("fields")) fields.sort(key = lambda e : e) + ignore = [10, 100] for n in fields: + if n in ignore: + continue for p in data.keys(): - data[p] = [RunForSteps(programs[p], "fields/"+str(n), 200), n] + data[p] = RunForSteps(programs[p], "fields/"+str(n), 200) #print(str(data[p])) - if (len(data[p]) > 0): - plot.replot(Gnuplot.Data(data[p][0], title=str(p)+":"+str(n), with_="lp linecolor "+str(fields.index(n)))) + + #print(str(data.items())); + for d in sorted(data.items(), key = lambda e : e[1][len(e[1])-1][1]): + if (len(d[1]) > 0): + plot.replot(Gnuplot.Data(d[1], title=str(d[0])+":"+str(n), with_="lp")) #linecolor "+str(fields.index(n)))) #print(str(data.items())) # Score the programs diff --git a/course/semester2/pprog/assignment1/mthread/nbody-slow b/course/semester2/pprog/assignment1/mthread/nbody-slow new file mode 100755 index 00000000..9680b55a Binary files /dev/null and b/course/semester2/pprog/assignment1/mthread/nbody-slow differ diff --git a/course/semester2/pprog/assignment1/mthread/nbody.c b/course/semester2/pprog/assignment1/mthread/nbody.c index 75049286..301cd8b1 100644 --- a/course/semester2/pprog/assignment1/mthread/nbody.c +++ b/course/semester2/pprog/assignment1/mthread/nbody.c @@ -18,7 +18,13 @@ System * sub_system = NULL; //Array of Systems used to divide up the main "unive pthread_mutex_t mutex_runstate; // Mutex around the runstate +#ifdef PERSISTENT_THREADS +Barrier force_barrier; // I laughed at this variable name. A bit sad really. +Barrier position_barrier; +#else Barrier worker_barrier; +#endif //PERSISTENT_THREADS + Barrier graphics_barrier; @@ -47,6 +53,10 @@ void * Compute_Thread(void * arg) options.num_threads = s->N; } + pthread_attr_t attr; //thread attribute for the workers. + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //Needs to be detached, so that memory can be reused. + if (options.num_threads > 1) // Allocate worker threads and sub systems, as long as there would be more than 1 { worker_thread = (pthread_t*)(calloc(options.num_threads, sizeof(pthread_t))); @@ -75,17 +85,39 @@ void * Compute_Thread(void * arg) if (i == options.num_threads - 1) sub_system[i].N += remainder; // The last thread gets the remainder + #ifdef PERSISTENT_THREADS + if (pthread_create(worker_thread+i, & attr, Worker_Thread, (void*)(sub_system+i)) != 0) + { + perror("In compute thread, couldn't create worker thread"); + QuitProgram(true); + pthread_exit(NULL); + } + #endif //PERSISTENT_THREADS + } - } - - pthread_attr_t attr; //thread attribute for the workers. - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //Needs to be detached, so that memory can be reused. + + } + #ifdef PERSISTENT_THREADS + else + { + while (!ExitCondition()) + { + if (options.verbosity != 0 && universe.steps % options.verbosity == 1) + { + DisplayStatistics(); + } - - + // Just do everything in this thread + System_Forces(s, s); + System_Positions(s); + continue; + } + QuitProgram(false); + pthread_exit(NULL); + } + #else // The main computation loop while (true) { @@ -110,6 +142,8 @@ void * Compute_Thread(void * arg) continue; } + + //Compute forces for (unsigned i = 0; i < options.num_threads; ++i) { @@ -154,8 +188,13 @@ void * Compute_Thread(void * arg) if (options.draw_graphics && options.pedantic_graphics) Barrier_Leave(&graphics_barrier); + + } + #endif //PERSISTENT_THREADS + + return NULL; } /** @@ -166,10 +205,19 @@ void * Compute_Thread(void * arg) */ void BeforeDraw() { + if (options.verbosity != 0 && universe.steps % options.verbosity == 0) + DisplayStatistics(); + //printf("BEFORE DRAW\n"); if (!options.pedantic_graphics) return; + #ifdef PERSISTENT_THREADS + Barrier_Wait(&position_barrier); + + #else Barrier_Wait(&graphics_barrier); - Barrier_Enter(&graphics_barrier); + #endif //PERSISTENT_THREADS + + Barrier_Enter(&graphics_barrier); } /** @@ -181,11 +229,54 @@ void BeforeDraw() */ void AfterDraw() { + universe.steps += 1; if (!options.pedantic_graphics) return; Barrier_Leave(&graphics_barrier); + } +#ifdef PERSISTENT_THREADS + +/** + * @function Worker_Thread + * @purpose Thread - Calculate stuff + */ +void * Worker_Thread(void * arg) +{ + System * s = (System*)(arg); + while (!ExitCondition()) + { + + Barrier_Enter(&force_barrier); + + System_Forces(s, &universe); + + Barrier_Leave(&force_barrier); + + //printf("Computed forces for %p\n", arg); + Barrier_Wait(&force_barrier); + //printf("Computed ALL forces\n"); + + if (options.draw_graphics && options.pedantic_graphics) + Barrier_Wait(&graphics_barrier); + + Barrier_Enter(&position_barrier); + + System_Positions(s); + + Barrier_Leave(&position_barrier); + //printf("Computed positions for %p\n", arg); + Barrier_Wait(&position_barrier); + //printf("Computed ALL positions\n"); + } + QuitProgram(false); + pthread_exit(NULL); +} + + +#else + /** * @function Force_Thread * @purpose Thread - Calculates the forces on objects in a System @@ -215,6 +306,8 @@ void * Position_Thread(void * s) return NULL; } +#endif //PERSISTENT_THREADS + /** * @function QuitProgram * @purpose This function can either be called by the main thread in order to signal other threads @@ -262,21 +355,34 @@ void Simulation_Run(int argc, char ** argv) { atexit(Thread_Cleanup); + #ifdef PERSISTENT_THREADS + Barrier_Init(&force_barrier); + Barrier_Init(&position_barrier); + #else Barrier_Init(&worker_barrier); + #endif //PERSISTENT_THREADS Barrier_Init(&graphics_barrier); + if (options.draw_graphics) { // The graphics are enabled, so create a thread to do computations // Graphics are done in the main loop + //printf("Graphics are enabled\n"); + #ifdef PERSISTENT_THREADS + Compute_Thread((void*)(&universe)); + #else if (pthread_create(&compute_thread, NULL, Compute_Thread, (void*)&universe) != 0) { perror("Error creating compute thread"); exit(EXIT_FAILURE); } + #endif //PERSISTENT_THREADS + //printf("Run compute thread\n"); Graphics_Run(argc, argv); } else + Compute_Thread((void*)(&universe)); // Graphics are disabled, so do computations in the main thread } diff --git a/course/semester2/pprog/assignment1/mthread/nbody.h b/course/semester2/pprog/assignment1/mthread/nbody.h index 59501263..7abe5250 100644 --- a/course/semester2/pprog/assignment1/mthread/nbody.h +++ b/course/semester2/pprog/assignment1/mthread/nbody.h @@ -10,7 +10,9 @@ #define DEFAULT_WORKING_THREADS 2 -#define PERSISTENT_THREADS //If defined, threads will not be continually destroyed and then respawned +//#define PERSISTENT_THREADS //If defined, threads will not be continually destroyed and then respawned + + //Undefine default macros, replace with functions #undef Simulation_Run @@ -26,10 +28,12 @@ void AfterDraw(); void * Compute_Thread(void * system); //Thread - Continuously perform computations for a System of bodies. May spawn additional worker threads. +#ifdef PERSISTENT_THREADS +void * Worker_Thread(void * arg); +#else void * Force_Thread(void * system); //Thread - Compute forces for all objects in a system void * Position_Thread(void * system); //Thread - Compute positions for all objects in a system - - +#endif //PERSISTENT_THREADS void Thread_Cleanup(void); //Called at program exit to safely join computation thread diff --git a/course/semester2/pprog/assignment1/openmp/nbody.c b/course/semester2/pprog/assignment1/openmp/nbody.c index c4872010..1d2f3690 100644 --- a/course/semester2/pprog/assignment1/openmp/nbody.c +++ b/course/semester2/pprog/assignment1/openmp/nbody.c @@ -133,6 +133,8 @@ void Compute(void) */ void BeforeDraw() { + if (options.verbosity != 0 && universe.steps % options.verbosity == 0) + DisplayStatistics(); if (!options.pedantic_graphics) return; while (graphics_busy == false); diff --git a/course/semester2/pprog/assignment1/single-thread/main.c b/course/semester2/pprog/assignment1/single-thread/main.c index 392c27d6..e9ccb411 100644 --- a/course/semester2/pprog/assignment1/single-thread/main.c +++ b/course/semester2/pprog/assignment1/single-thread/main.c @@ -85,7 +85,7 @@ int main(int argc, char** argv) options.start_clock = clock(); //Get CPU cycles executed before simulation starts Simulation_Run(argc, argv); // Start the simulation - printf("Got here!\n"); + //printf("Got here!\n"); exit(EXIT_FAILURE); //Should never get to this line } diff --git a/course/semester2/pprog/assignment1/single-thread/nbody.h b/course/semester2/pprog/assignment1/single-thread/nbody.h index a0415748..4d53f9d0 100644 --- a/course/semester2/pprog/assignment1/single-thread/nbody.h +++ b/course/semester2/pprog/assignment1/single-thread/nbody.h @@ -33,7 +33,7 @@ else \ //Macro to be overwritten in multithreaded versions, called before the graphics is allowed to draw anything #define BeforeDraw() \ -if (options.verbosity != 0 && universe.steps % options.verbosity == 1) \ +if (options.verbosity != 0 && universe.steps % options.verbosity == 0) \ DisplayStatistics(); \ System_Compute(&universe);