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)})
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):
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
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;
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)));
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)
{
continue;
}
+
+
//Compute forces
for (unsigned i = 0; i < options.num_threads; ++i)
{
if (options.draw_graphics && options.pedantic_graphics)
Barrier_Leave(&graphics_barrier);
+
+
}
+ #endif //PERSISTENT_THREADS
+
+ return NULL;
}
/**
*/
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);
}
/**
*/
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
return NULL;
}
+#endif //PERSISTENT_THREADS
+
/**
* @function QuitProgram
* @purpose This function can either be called by the main thread in order to signal other threads
{
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
}