diff --git a/src/engine.c b/src/engine.c index b3f1b77e6116b87aaace357921d2bad19f638912..c0591a6f945dc18cc5feddac332bf53e56f79337 100644 --- a/src/engine.c +++ b/src/engine.c @@ -2503,19 +2503,18 @@ void engine_print_stats(struct engine *e) { /* } */ #endif - // const double e_tot = e_kin + e_int + e_pot; + const double E_tot = stats.E_kin + stats.E_int + stats.E_pot; /* Print info */ - /* if (e->nodeID == 0) { */ - /* fprintf(e->file_stats, */ - /* " %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e - * %14e " */ - /* "%14e\n", */ - /* e->time, mass, e_tot, e_kin, e_int, e_pot, e_rad, entropy, - * mom[0], */ - /* mom[1], mom[2], ang_mom[0], ang_mom[1], ang_mom[2]); */ - /* fflush(e->file_stats); */ - /* } */ + if (e->nodeID == 0) { + fprintf(e->file_stats, + " %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e %14e " + "%14e\n", + e->time, stats.mass, E_tot, stats.E_kin, stats.E_int, stats.E_pot, + stats.E_rad, stats.entropy, stats.mom[0], stats.mom[1], + stats.mom[2], stats.ang_mom[0], stats.ang_mom[1], stats.ang_mom[2]); + fflush(e->file_stats); + } if (e->verbose) message("took %.3f %s.", clocks_from_ticks(getticks() - tic), @@ -2726,12 +2725,6 @@ void engine_step(struct engine *e) { fflush(e->file_timesteps); } - /* Save some statistics */ - if (e->time - e->timeLastStatistics >= e->deltaTimeStatistics) { - engine_print_stats(e); - e->timeLastStatistics += e->deltaTimeStatistics; - } - /* Drift only the necessary particles, that means all particles * if we are about to repartition. */ int repart = (e->forcerepart != REPART_NONE); @@ -2828,6 +2821,12 @@ void engine_step(struct engine *e) { engine_launch(e, e->nr_threads, mask, submask); TIMER_TOC(timer_runners); + /* Save some statistics */ + if (e->time - e->timeLastStatistics >= e->deltaTimeStatistics) { + engine_print_stats(e); + e->timeLastStatistics += e->deltaTimeStatistics; + } + TIMER_TOC2(timer_step); clocks_gettime(&time2); diff --git a/src/statistics.c b/src/statistics.c index dfa65516c2d1441b82f0f8ab9d7781d321ef6a32..ba36e0c44470fa8cdbdb51cf7e4e731620253c78 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -27,6 +27,7 @@ #include "statistics.h" /* Local headers. */ +#include "atomic.h" #include "cooling.h" #include "engine.h" #include "error.h" @@ -38,8 +39,6 @@ */ struct index_data { const struct space *s; - int chunk_size; - int num_threads; struct statistics *stats; }; @@ -50,10 +49,9 @@ void stats_collect_part_mapper(void *map_data, int nr_parts, void *extra_data) { const struct space *s = data->s; struct part *restrict parts = (struct part *)map_data; struct xpart *restrict xparts = s->xparts + (ptrdiff_t)(parts - s->parts); - const int chunk_size = data->chunk_size; - const int num_threads = data->num_threads; const int ti_current = s->e->ti_current; const double timeBase = s->e->timeBase; + struct statistics *const global_stats = data->stats; /* Local accumulator */ struct statistics stats; @@ -97,61 +95,35 @@ void stats_collect_part_mapper(void *map_data, int nr_parts, void *extra_data) { stats.entropy += m * hydro_get_entropy(p, dt); } - /* Where do we write back ? */ - const int thread_id = - ((ptrdiff_t)(parts - s->parts) / chunk_size) % num_threads; - /* Now write back to memory */ - data->stats[thread_id].E_kin += stats.E_kin; - data->stats[thread_id].E_int += stats.E_int; - data->stats[thread_id].E_pot += stats.E_pot; - data->stats[thread_id].E_rad += stats.E_rad; - data->stats[thread_id].entropy += stats.entropy; - data->stats[thread_id].mass += stats.mass; - data->stats[thread_id].mom[0] += stats.mom[0]; - data->stats[thread_id].mom[1] += stats.mom[1]; - data->stats[thread_id].mom[2] += stats.mom[2]; - data->stats[thread_id].ang_mom[0] += stats.ang_mom[0]; - data->stats[thread_id].ang_mom[1] += stats.ang_mom[1]; - data->stats[thread_id].ang_mom[2] += stats.ang_mom[2]; + if (lock_lock(&global_stats->lock) == 0) { + + global_stats->E_int += stats.E_int; + global_stats->E_pot += stats.E_pot; + global_stats->E_rad += stats.E_rad; + global_stats->entropy += stats.entropy; + global_stats->mass += stats.mass; + global_stats->mom[0] += stats.mom[0]; + global_stats->mom[1] += stats.mom[1]; + global_stats->mom[2] += stats.mom[2]; + global_stats->ang_mom[0] += stats.ang_mom[0]; + global_stats->ang_mom[1] += stats.ang_mom[1]; + global_stats->ang_mom[2] += stats.ang_mom[2]; + } + if (lock_unlock(&global_stats->lock) != 0) + error("Failed to unlock stats holder."); } void stats_collect(const struct space *s, struct statistics *stats) { - const int num_threads = s->e->threadpool.num_threads; - const int chunk_size = s->nr_parts / num_threads; + const int chunk_size = 1000; /* Prepare the data */ struct index_data extra_data; extra_data.s = s; - extra_data.chunk_size = chunk_size; - extra_data.num_threads = num_threads; - extra_data.stats = malloc(sizeof(struct statistics) * num_threads); - if (extra_data.stats == NULL) - error("Impossible to allocate memory for statistics"); - bzero(&extra_data.stats, sizeof(struct statistics) * num_threads); + extra_data.stats = stats; /* Run parallel collection of statistics */ threadpool_map(&s->e->threadpool, stats_collect_part_mapper, s->parts, s->nr_parts, sizeof(struct part), chunk_size, &extra_data); - - /* Collect data from all the threads in the pool */ - for (int i = 0; i < num_threads; ++i) { - - stats->E_kin += extra_data.stats[i].E_kin; - stats->E_int += extra_data.stats[i].E_int; - stats->E_pot += extra_data.stats[i].E_pot; - stats->E_rad += extra_data.stats[i].E_rad; - stats->entropy += extra_data.stats[i].entropy; - stats->mass += extra_data.stats[i].mass; - stats->mom[0] += extra_data.stats[i].mom[0]; - stats->mom[1] += extra_data.stats[i].mom[1]; - stats->mom[2] += extra_data.stats[i].mom[2]; - stats->ang_mom[0] += extra_data.stats[i].ang_mom[0]; - stats->ang_mom[1] += extra_data.stats[i].ang_mom[1]; - stats->ang_mom[2] += extra_data.stats[i].ang_mom[2]; - } - - /* Free stuff */ - free(extra_data.stats); } diff --git a/src/statistics.h b/src/statistics.h index 4931d33cb351d394237621a8b3ac79bdb5cc100e..1910e3e2becd79e482508c6d56608a848fa938b7 100644 --- a/src/statistics.h +++ b/src/statistics.h @@ -23,6 +23,7 @@ #include "../config.h" /* Local headers. */ +#include "lock.h" #include "space.h" /** @@ -53,6 +54,9 @@ struct statistics { /*! Angular momentum */ double ang_mom[3]; + + /*! Lock for threaded access */ + swift_lock_type lock; }; void stats_collect(const struct space* s, struct statistics* stats);