Parallel Programming - Start OpenMP Version
authorSam Moore <sam@daedalus.(none)>
Sun, 9 Sep 2012 10:53:14 +0000 (18:53 +0800)
committerSam Moore <sam@daedalus.(none)>
Sun, 9 Sep 2012 10:53:14 +0000 (18:53 +0800)
Almost finished

14 files changed:
course/semester2/pprog/assignment1/mthread/nbody.c
course/semester2/pprog/assignment1/mthread/nbody.h
course/semester2/pprog/assignment1/openmp/Makefile [new symlink]
course/semester2/pprog/assignment1/openmp/graphics.c [new symlink]
course/semester2/pprog/assignment1/openmp/graphics.h [new symlink]
course/semester2/pprog/assignment1/openmp/main.c [new symlink]
course/semester2/pprog/assignment1/openmp/nbody.c [new file with mode: 0644]
course/semester2/pprog/assignment1/openmp/nbody.h [new file with mode: 0644]
course/semester2/pprog/assignment1/single-thread/Makefile
course/semester2/pprog/assignment1/single-thread/graphics.c
course/semester2/pprog/assignment1/single-thread/graphics.h
course/semester2/pprog/assignment1/single-thread/main.c
course/semester2/pprog/assignment1/single-thread/nbody.c
course/semester2/pprog/assignment1/single-thread/nbody.h

index afd1d60..42b97cf 100644 (file)
@@ -7,6 +7,8 @@
 #include "nbody.h" // Declarations
 #include "../single-thread/nbody.c" // Include all functions from the single threaded version
 
+#include "graphics.h" // For declaration of Graphics_Run only
+
 // --- Variable declarations --- //
 
 pthread_t compute_thread; // The thread responsible for computations; it spawns worker threads
@@ -86,19 +88,16 @@ void * Compute_Thread(void * arg)
        while (true)
        {
                
-               if (runstate != RUN) pthread_exit(NULL); //Check whether the main thread wants to exit
+               if (runstate != RUN) pthread_exit(NULL); //Check whether the thread needs to exit
 
 
        
                //Check whether the program should quit due to steps being computed, or a timeout
-               if (options.timeout > 0.0)
+               if (ExitCondition())
                {
-                       if ((unsigned)(time(NULL) - options.start_time.tv_sec) >= options.timeout)
-                               QuitProgram(false);
-               }
-
-               if (options.num_steps > 0 && universe.steps > options.num_steps)
                        QuitProgram(false);
+                       continue; // The check at the start of the next loop will stop the thread
+               }
 
                if (options.draw_graphics == false && options.verbosity != 0 
                        && universe.steps % options.verbosity == 1)
@@ -217,7 +216,8 @@ void * Position_Thread(void * s)
  */
 void QuitProgram(bool error)
 {
-       
+       if (runstate == QUIT || runstate == QUIT_ERROR)
+               return; //Don't do anything if already quitting
        pthread_mutex_lock(&mutex_runstate); // aquire mutex
        if (error) // set the runstate
                runstate = QUIT_ERROR;
@@ -247,29 +247,24 @@ void Thread_Cleanup(void)
  * @function Simulation_Run
  * @purpose Initialise and start the simulation. Will be called in the main thread.
  *     Replaces the single-threaded macro that does nothing, and sets up the compute thread
+ * @param argc - Number of arguments - Passed to Graphics_Run if needed
+ * @param argv - Argument strings - Passed to Graphics_Run if needed
  */
-void Simulation_Run()
+void Simulation_Run(int argc, char ** argv)
 {
        atexit(Thread_Cleanup);
 
-       if (options.draw_graphics == false)
-       {
-               Compute_Thread((void*)(&universe));
-
-               // If there are no graphics, run the computation loop in the main thread
-               // The call to pthread_exit(NULL) in the computation loop ends the main thread
-
-               // This means the main function never calls the Graphics_Run function
-               // Without this condition here, Graphics_Display would essentially be running a busy loop in the main thread
-               
-               fprintf(stderr,"Should not see this\n");
-               exit(EXIT_FAILURE);
-       }
-       
-       // Create a thread to handle computation loop
-       if (pthread_create(&compute_thread, NULL, Compute_Thread, (void*)&universe) != 0)
+       if (options.draw_graphics)
        {
-               perror("Error creating compute thread");
-               exit(EXIT_FAILURE);
+               // The graphics are enabled, so create a thread to do computations
+               // Graphics are done in the main loop
+               if (pthread_create(&compute_thread, NULL, Compute_Thread, (void*)&universe) != 0)
+               {
+                       perror("Error creating compute thread");
+                       exit(EXIT_FAILURE);
+               }
+               Graphics_Run(argc, argv);
        }
+       else
+               Compute_Thread((void*)(&universe)); // Graphics are disabled, so do computations in the main thread
 }
index 9b76bc7..0b3208a 100644 (file)
@@ -12,7 +12,7 @@
 
 //Undefine default macros, replace with functions
 #undef Simulation_Run
-void Simulation_Run(void);
+void Simulation_Run(int argc, char ** argv);
 #undef QuitProgram
 void QuitProgram(bool error);
 
diff --git a/course/semester2/pprog/assignment1/openmp/Makefile b/course/semester2/pprog/assignment1/openmp/Makefile
new file mode 120000 (symlink)
index 0000000..b0d614d
--- /dev/null
@@ -0,0 +1 @@
+../single-thread/Makefile
\ No newline at end of file
diff --git a/course/semester2/pprog/assignment1/openmp/graphics.c b/course/semester2/pprog/assignment1/openmp/graphics.c
new file mode 120000 (symlink)
index 0000000..6fc2284
--- /dev/null
@@ -0,0 +1 @@
+../single-thread/graphics.c
\ No newline at end of file
diff --git a/course/semester2/pprog/assignment1/openmp/graphics.h b/course/semester2/pprog/assignment1/openmp/graphics.h
new file mode 120000 (symlink)
index 0000000..aebee13
--- /dev/null
@@ -0,0 +1 @@
+../single-thread/graphics.h
\ No newline at end of file
diff --git a/course/semester2/pprog/assignment1/openmp/main.c b/course/semester2/pprog/assignment1/openmp/main.c
new file mode 120000 (symlink)
index 0000000..37e5985
--- /dev/null
@@ -0,0 +1 @@
+../single-thread/main.c
\ No newline at end of file
diff --git a/course/semester2/pprog/assignment1/openmp/nbody.c b/course/semester2/pprog/assignment1/openmp/nbody.c
new file mode 100644 (file)
index 0000000..6998892
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * @file nbody.c
+ * @purpose OpenMP version of N-Body simulator, implementation
+ * @author Sam Moore (20503628) - 2012
+ */
+
+#include "nbody.h"
+#include "../single-thread/nbody.c" // Include original code
+#include "graphics.h" // For Graphics_Run function only
+
+/**
+ * @function Simulation_Run
+ * @purpose Start the simulation
+ * @param argc, argv - Passed to Graphics_Run if needed, otherwise unused
+ */
+void Simulation_Run(int argc, char ** argv)
+{      
+       omp_set_nested(1);
+       if (omp_get_nested() != 1)
+       {
+               fprintf(stderr, "Couldn't set nested parallelism, I kind of need that\n");
+               exit(EXIT_FAILURE);
+       }       
+               
+
+       if (options.num_threads == 0)
+               options.num_threads = omp_get_max_threads();
+
+       if (options.draw_graphics)
+               omp_set_num_threads(2);
+       else
+               omp_set_num_threads(1);
+
+
+               
+
+       #pragma omp parallel sections
+       {
+               
+               #pragma omp section
+               {
+                       omp_set_num_threads(options.num_threads);
+                       while (true)
+                       {
+                               
+                               if (runstate != RUN) break; //Check whether the main thread wants to exit
+                               
+                               if (ExitCondition())
+                               {
+                                       break;
+                               }                               
+
+
+                               if (options.draw_graphics == false && options.verbosity != 0 
+                                       && universe.steps % options.verbosity == 1)
+                               {
+                                       DisplayStatistics();
+                               }
+                               
+                                               
+                               Compute();
+                       }
+               }
+
+               #pragma omp section
+               {
+                       if (options.draw_graphics)
+                               Graphics_Run(argc, argv);
+                       printf("Got to bit after Graphics_Run()\n");
+               }
+
+       }
+}
+
+/**
+ * @function Compute
+ * @purpose Compute a single step, multithreaded using OpenMP
+ */
+void Compute(void)
+{
+       //printf("There are %d threads working and %d available\n", omp_get_num_threads(), omp_get_max_threads());
+       //return;
+       unsigned n_per_thread = (universe.N) / options.num_threads;
+       unsigned remainder = (universe.N) % options.num_threads;
+       #pragma omp parallel for
+       for (unsigned i = 0; i < options.num_threads; ++i)
+       {
+               //printf("Thread %d executes iteration %u\n", omp_get_thread_num(), i);
+               System s;
+               s.body = universe.body + (i * n_per_thread);
+               s.N = (i == options.num_threads - 1) ? n_per_thread : n_per_thread + remainder;
+               System_Forces(&s, &universe);
+       }
+
+       #pragma omp parallel for
+       for (unsigned i = 0; i < options.num_threads; ++i)
+       {
+               //printf("Thread %d executes iteration %u\n", omp_get_thread_num(), i);
+               System s;
+               s.body = universe.body + (i * n_per_thread);
+               s.N = (i == options.num_threads - 1) ? n_per_thread : n_per_thread + remainder;
+               System_Positions(&s);
+       }
+
+       universe.steps += 1;
+
+}
diff --git a/course/semester2/pprog/assignment1/openmp/nbody.h b/course/semester2/pprog/assignment1/openmp/nbody.h
new file mode 100644 (file)
index 0000000..b7d0b41
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _NBODY_OPENMP_H
+#define _NBODY_OPENMP_H
+
+/**
+ * @file nbody.h
+ * @purpose OpenMP version of N-Body simulator, declarations
+ * @author Sam Moore (20503628) - 2012
+ */
+
+#include "../single-thread/nbody.h" //Include original code
+#include <omp.h>
+
+
+#undef SINGLE_THREADED
+#define OMP_THREADED
+
+// Replace default macros with thread-safe functions
+#undef Simulation_Run
+void Simulation_Run(int argc, char ** argv);
+//#undef QuitProgram
+//void QuitProgram(bool error); 
+
+void Compute(); //Compute a single step
+
+#endif //_NBODY_OPENMP_H
+
+//EOF
index f34eab2..b164037 100644 (file)
@@ -11,7 +11,7 @@ LINK_OBJ = main.o nbody.o graphics.o
 BIN = nbody
 
 $(BIN) : $(LINK_OBJ) 
-       $(CXX) -o $(BIN) $(LINK_OBJ) $(LIBRARIES)
+       $(CXX) -o $(BIN) $(LINK_OBJ) $(PREPROCESSOR_FLAGS) $(LIBRARIES)
 
 nbody : 
 
index e3722e9..1b4fcb3 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "graphics.h" //Function declarations
 #include "nbody.h" //The simulation
+#include <GL/freeglut.h>
 
 // --- Variable definitions --- //
 double previousTime, eyeTheta, eyePhi, eyeRho;
@@ -106,37 +107,34 @@ void Graphics_Run(int argc, char ** argv)
  */
 void Graphics_Display() 
 {
+       //Check whether the program should quit due to steps being computed, or a timeout
+       if (ExitCondition())
+       {
+               glutLeaveMainLoop();
+               return;
+       }
 
 
-       if (options.verbosity != 0 && universe.steps % options.verbosity == 1)
-               DisplayStatistics();
-
        #ifdef SINGLE_THREADED
+               if (options.verbosity != 0 && universe.steps % options.verbosity == 1)
+                       DisplayStatistics();
                System_Compute(&universe);
-
-               //Check whether the program should quit due to steps being computed, or a timeout
-               if (options.timeout > 0.0)
-               {
-                       if ((unsigned)(time(NULL) - options.start_time.tv_sec) >= options.timeout)
-                               exit(EXIT_SUCCESS);
-               }
-               if (options.num_steps > 0 && universe.steps > options.num_steps)
-                       exit(EXIT_SUCCESS);
-
-
        #endif
 
 
+
        //Check whether the runstate has been set to quit the program
        switch (runstate)
        {
                case RUN:
                        break;
                case QUIT:
-                       exit(EXIT_SUCCESS);
+                       glutLeaveMainLoop();
+                       return;
                        break;
                case QUIT_ERROR:
-                       exit(EXIT_FAILURE);
+                       glutLeaveMainLoop();
+                       return;
                        break;
        }
 
@@ -172,7 +170,8 @@ void Graphics_Keyboard(unsigned char theKey, int mouseX, int mouseY)
 {
        if (theKey == 'x' || theKey == 'X') 
        {
-               exit(EXIT_SUCCESS);
+               glutLeaveMainLoop();
+               return;
        }
 
                if (theKey == 'i' || theKey == 'I') {
index 2fbc0a6..c2b99f3 100644 (file)
@@ -28,7 +28,7 @@
 #define WORLD_FAR 1000000
 #define BALL_SIZE 0.5
 #define REFRESH_RATE 0.001
-#define LINE_SIZE 1000
+
 
 void Graphics_Run(int argc, char ** argv);
 void Graphics_Display(void);
index f9f3b52..4b0c48a 100644 (file)
@@ -80,9 +80,9 @@ int main(int argc, char** argv)
        }
        
        options.start_clock = clock(); //Get CPU cycles executed before simulation starts
-       Simulation_Run(); // Start the simulation
-       Graphics_Run(argc, argv); //Start the graphics loop
-
+       Simulation_Run(argc, argv); // Start the simulation
+       
+       printf("Got here!\n");
        exit(EXIT_FAILURE); //Should never get to this line
 }
 
index 47820d1..67c36d3 100644 (file)
@@ -136,7 +136,6 @@ void System_Positions(System * s)
  * @param s - The System
  * @param fileName - The input file
  */
-#define LINE_SIZE BUFSIZ
 void System_Init(System * s, const char *fileName) 
 {
        char line[LINE_SIZE];
@@ -226,3 +225,15 @@ void DisplayStatistics()
        printf("%u\t%f\t%u\t%f\n", universe.steps, runtime, (unsigned)(end - options.start_clock), clock_time);
 }
 
+
+/**
+ * @function ExitCondition
+ * @purpose Helper to check whether the program is supposed to exit
+ *     Does not check for user triggered quit
+ *     Checks for either a timeout, or computation of the required number of steps
+ */
+bool ExitCondition(void)
+{
+       return ((options.timeout > 0.00 && ((unsigned)(time(NULL) - options.start_time.tv_sec) >= options.timeout))
+               || (options.num_steps > 0 && universe.steps > options.num_steps));
+}
index b8c9813..fc19d05 100644 (file)
 #define SINGLE_THREADED
 
 //These macros will be undefined by the multithreaded versions
-#define Simulation_Run() //Sets up the simulation; in multithreaded versions, will spawn threads
+#define Simulation_Run(argc, argv) (Graphics_Run(argc, argv)) //Sets up the simulation; in multithreaded versions, will spawn threads
 #define QuitProgram(error) (runstate = (error == true) ? QUIT : QUIT_ERROR) //Prepares to exit program, is thread safe in multithreaded versions
 
 #define M_PI        3.14159265358979323846264338327950288   /* pi */
 #define G 6.67428E-11
 #define DELTA_T 0.05
 #define DIMENSIONS 3
+#define LINE_SIZE 1000
 #define square(x) ((x)*(x))
 
 
@@ -95,6 +96,8 @@ void Universe_Cleanup(); //Cleanup universe and write bodies to file
 void DisplayStatistics(); // Print information about steps computed, total (real) runtime, and CPU cycles
 
 
+bool ExitCondition(void); //Checks whether the program is supposed to exit automatically yet (ie: other than the user pressing "quit")
+
 
 typedef enum {RUN, QUIT, QUIT_ERROR} RUNSTATE;
 extern RUNSTATE runstate; // Set runstate to QUIT or QUIT_ERROR and the simulation will stop on the next step.

UCC git Repository :: git.ucc.asn.au