3 * @purpose OpenMP version of N-Body simulator, implementation
4 * @author Sam Moore (20503628) - 2012
8 #include "../single-thread/nbody.c" // Include original code
9 #include "graphics.h" // For Graphics_Run function only
11 omp_lock_t graphics_lock;
12 bool graphics_busy = false;
15 * @function Simulation_Run
16 * @purpose Start the simulation
17 * @param argc, argv - Passed to Graphics_Run if needed, otherwise unused
19 void Simulation_Run(int argc, char ** argv)
22 if (omp_get_nested() != 1)
24 fprintf(stderr, "Couldn't set nested parallelism, I kind of need that\n");
29 if (options.num_threads == 0)
30 options.num_threads = omp_get_max_threads();
32 if (options.draw_graphics)
33 omp_set_num_threads(2);
35 omp_set_num_threads(1);
38 omp_init_lock(&graphics_lock);
40 #pragma omp parallel sections
45 omp_set_num_threads(options.num_threads);
49 if (runstate != RUN) break; //Check whether the main thread wants to exit
56 if (options.verbosity != 0 && universe.steps % options.verbosity == 1)
64 //printf("Left compute loop\n");
69 if (options.draw_graphics)
70 Graphics_Run(argc, argv);
71 //printf("Got to bit after Graphics_Run()\n");
76 omp_destroy_lock(&graphics_lock);
81 * @purpose Compute a single step, multithreaded using OpenMP
85 //printf("There are %d threads working and %d available\n", omp_get_num_threads(), omp_get_max_threads());
87 unsigned n_per_thread = (universe.N) / options.num_threads;
88 unsigned remainder = (universe.N) % options.num_threads;
89 #pragma omp parallel for
90 for (unsigned i = 0; i < options.num_threads; ++i)
92 //printf("Thread %d executes iteration %u\n", omp_get_thread_num(), i);
94 s.body = universe.body + (i * n_per_thread);
95 s.N = (i == options.num_threads - 1) ? n_per_thread : n_per_thread + remainder;
96 System_Forces(&s, &universe);
99 // Wait for graphics to finish drawing
101 if (options.draw_graphics && options.pedantic_graphics)
103 while (graphics_busy);
106 #pragma omp parallel for
107 for (unsigned i = 0; i < options.num_threads; ++i)
109 //printf("Thread %d executes iteration %u\n", omp_get_thread_num(), i);
111 s.body = universe.body + (i * n_per_thread);
112 s.N = (i == options.num_threads - 1) ? n_per_thread : n_per_thread + remainder;
113 System_Positions(&s);
118 // Tell graphics to continue
119 if (options.draw_graphics && options.pedantic_graphics)
121 omp_set_lock(&graphics_lock);
122 graphics_busy = true;
123 omp_unset_lock(&graphics_lock);
130 * @function BeforeDraw
131 * @purpose Called before the graphics thread draws bodies.
132 * If pedantic graphics are used, will wait until graphics_busy is set to true before drawing
136 if (options.verbosity != 0 && universe.steps % options.verbosity == 0)
138 if (!options.pedantic_graphics)
140 while (graphics_busy == false);
144 * @function AfterDraw
145 * @purpose Called after the graphics thread draws bodies
146 * If pedantic graphics used, will unset graphics_busy when done drawing
150 if (!options.pedantic_graphics)
152 omp_set_lock(&graphics_lock);
153 graphics_busy = false;
154 omp_unset_lock(&graphics_lock);