diff --git a/examples/main.c b/examples/main.c index dcc113ab6af6a06e7c20ac1aac7c2d3b715f7ef3..11163b42523fa5b1de1438ad8e67dde0fe9c88ef 100644 --- a/examples/main.c +++ b/examples/main.c @@ -45,6 +45,9 @@ #define ENGINE_POLICY engine_policy_none #endif +/* Global profiler. */ +struct profiler prof; + /** * @brief Help messages for the command line parameters. */ diff --git a/src/Makefile.am b/src/Makefile.am index 18da59c2b04f50cac29d948bdbe502bc2f70bec2..826ec687d0b9c72768a798ba692755258320227f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,8 +44,7 @@ include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \ common_io.h single_io.h multipole.h map.h tools.h partition.h clocks.h parser.h \ physical_constants.h physical_constants_cgs.h potential.h version.h \ hydro_properties.h riemann.h threadpool.h cooling.h cooling_struct.h sourceterms.h \ - sourceterms_struct.h statistics.h memswap.h - + sourceterms_struct.h statistics.h memswap.h profiler.h # Common source files AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \ @@ -54,7 +53,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \ kernel_hydro.c tools.c part.c partition.c clocks.c parser.c \ physical_constants.c potential.c hydro_properties.c \ runner_doiact_fft.c threadpool.c cooling.c sourceterms.c \ - statistics.c + statistics.c profiler.c # Include files for distribution, not installation. nobase_noinst_HEADERS = align.h approx_math.h atomic.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \ diff --git a/src/engine.c b/src/engine.c index e989aefd5343eb7f377c6c1e8bc41f9875f2f42e..d604042fffd2f9b8f5677cba72d61e9d75b6a311 100644 --- a/src/engine.c +++ b/src/engine.c @@ -59,6 +59,7 @@ #include "parallel_io.h" #include "part.h" #include "partition.h" +#include "profiler.h" #include "proxy.h" #include "runner.h" #include "serial_io.h" diff --git a/src/profiler.c b/src/profiler.c new file mode 100644 index 0000000000000000000000000000000000000000..8e7299b187f1037a5bdcea13edd2f524fdf4cd36 --- /dev/null +++ b/src/profiler.c @@ -0,0 +1,228 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2016 James S. Willis (james.s.willis@durham.ac.uk) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ + +/* Config parameters. */ +#include "../config.h" + +/* Some standard headers. */ +#include <string.h> + +/* This object's header. */ +#include "profiler.h" + +/** + * @brief Resets all timers. + * + * @param (return) profiler #profiler object that holds file pointers and + * function timers. + */ +void profiler_reset_timers(struct profiler *profiler) { + + profiler->collect_timesteps_time = 0; + profiler->drift_time = 0; + profiler->rebuild_time = 0; + profiler->reweight_time = 0; + profiler->clear_waits_time = 0; + profiler->re_wait_time = 0; + profiler->enqueue_time = 0; + profiler->stats_time = 0; + profiler->launch_time = 0; + profiler->space_rebuild_time = 0; + profiler->engine_maketasks_time = 0; + profiler->engine_marktasks_time = 0; + profiler->space_regrid_time = 0; + profiler->space_parts_sort_time = 0; + profiler->space_split_time = 0; + profiler->space_parts_get_cell_id_time = 0; + profiler->space_count_parts_time = 0; +} + +/** + * @brief Opens an output file and populates the header. + * + * @param e #engine object to get various properties. + * @param fileName name of file to be written to. + * @param functionName name of function that is being timed. + * @param (return) file pointer used to open output file. + */ +void profiler_write_timing_info_header(struct engine *e, char *fileName, + char *functionName, FILE **file) { + + /* Create the file name in the format: "fileName_(no. of threads)" */ + char fullFileName[200] = ""; + sprintf(fullFileName + strlen(fullFileName), "%s_%d.txt", fileName, + e->nr_nodes * e->nr_threads); + + /* Open the file and write the header. */ + *file = fopen(fullFileName, "w"); + fprintf(*file, + "# Host: %s\n# Branch: %s\n# Revision: %s\n# Compiler: %s, " + "Version: %s \n# " + "Number of threads: %d\n# Number of MPI ranks: %d\n# Hydrodynamic " + "scheme: %s\n# Hydrodynamic kernel: %s\n# No. of neighbours: %.2f " + "+/- %.2f\n# Eta: %f\n" + "# %6s %14s %14s %10s %10s %16s [%s]\n", + hostname(), functionName, git_revision(), compiler_name(), + compiler_version(), e->nr_threads, e->nr_nodes, SPH_IMPLEMENTATION, + kernel_name, e->hydro_properties->target_neighbours, + e->hydro_properties->delta_neighbours, + e->hydro_properties->eta_neighbours, "Step", "Time", "Time-step", + "Updates", "g-Updates", "Wall-clock time", clocks_getunit()); + + fflush(*file); +} + +/** + * @brief Writes the headers for all output files. Should be called once at the + * start of the simulation, it could be called in engine_init() for example. + * + * @param e #engine object to get various properties. + * @param (return) profiler #profiler object that holds file pointers and + * function timers. + */ +void profiler_write_all_timing_info_headers(struct engine *e, + struct profiler *profiler) { + + profiler_write_timing_info_header(e, "enginecollecttimesteps", + "engine_collect_timesteps", + &profiler->file_engine_collect_timesteps); + profiler_write_timing_info_header(e, "enginedrift", "engine_drift", + &profiler->file_engine_drift); + profiler_write_timing_info_header(e, "enginerebuild", "engine_rebuild", + &profiler->file_engine_rebuild); + profiler_write_timing_info_header(e, "schedulerreweight", + "scheduler_reweight", + &profiler->file_scheduler_reweight); + profiler_write_timing_info_header(e, "schedulerclearwaits", + "scheduler_clear_waits", + &profiler->file_scheduler_clear_waits); + profiler_write_timing_info_header(e, "schedulerrewait", "scheduler_rewait", + &profiler->file_scheduler_re_wait); + profiler_write_timing_info_header(e, "schedulerenqueue", "scheduler_enqueue", + &profiler->file_scheduler_enqueue); + profiler_write_timing_info_header(e, "engineprintstats", "engine_print_stats", + &profiler->file_engine_stats); + profiler_write_timing_info_header(e, "enginelaunch", "engine_launch", + &profiler->file_engine_launch); + profiler_write_timing_info_header(e, "spacerebuild", "space_rebuild", + &profiler->file_space_rebuild); + profiler_write_timing_info_header(e, "enginemaketasks", "engine_maketasks", + &profiler->file_engine_maketasks); + profiler_write_timing_info_header(e, "enginemarktasks", "engine_marktasks", + &profiler->file_engine_marktasks); + profiler_write_timing_info_header(e, "spaceregrid", "space_regrid", + &profiler->file_space_regrid); + profiler_write_timing_info_header(e, "spacepartssort", "space_parts_sort", + &profiler->file_space_parts_sort); + profiler_write_timing_info_header(e, "spacesplit", "space_split", + &profiler->file_space_split); + profiler_write_timing_info_header(e, "spacegetcellid", "space_get_cell_id", + &profiler->file_space_parts_get_cell_id); + profiler_write_timing_info_header(e, "spacecountparts", "space_count_parts", + &profiler->file_space_count_parts); +} + +/** + * @brief Writes timing info to the output file. + * + * @param e #engine object to get various properties. + * @param time #ticks time in ticks to be written to the output file. + * @param (return) file pointer used to open output file. + */ +void profiler_write_timing_info(struct engine *e, ticks time, FILE **file) { + + fprintf(*file, " %6d %14e %14e %10zu %10zu %21.3f\n", e->step, e->time, + e->timeStep, e->updates, e->g_updates, clocks_from_ticks(time)); + fflush(*file); +} + +/** + * @brief Writes timing info to all output files. Should be called at the end of + * every time step, in engine_step() for example. + * + * @param e #engine object to get various properties. + * @param (return) profiler #profiler object that holds file pointers and + * function timers. + */ +void profiler_write_all_timing_info(struct engine *e, + struct profiler *profiler) { + + profiler_write_timing_info(e, profiler->drift_time, + &profiler->file_engine_drift); + profiler_write_timing_info(e, profiler->rebuild_time, + &profiler->file_engine_rebuild); + profiler_write_timing_info(e, profiler->reweight_time, + &profiler->file_scheduler_reweight); + profiler_write_timing_info(e, profiler->clear_waits_time, + &profiler->file_scheduler_clear_waits); + profiler_write_timing_info(e, profiler->re_wait_time, + &profiler->file_scheduler_re_wait); + profiler_write_timing_info(e, profiler->enqueue_time, + &profiler->file_scheduler_enqueue); + profiler_write_timing_info(e, profiler->stats_time, + &profiler->file_engine_stats); + profiler_write_timing_info(e, profiler->launch_time, + &profiler->file_engine_launch); + profiler_write_timing_info(e, profiler->space_rebuild_time, + &profiler->file_space_rebuild); + profiler_write_timing_info(e, profiler->engine_maketasks_time, + &profiler->file_engine_maketasks); + profiler_write_timing_info(e, profiler->engine_marktasks_time, + &profiler->file_engine_marktasks); + profiler_write_timing_info(e, profiler->space_regrid_time, + &profiler->file_space_regrid); + profiler_write_timing_info(e, profiler->space_parts_sort_time, + &profiler->file_space_parts_sort); + profiler_write_timing_info(e, profiler->space_split_time, + &profiler->file_space_split); + profiler_write_timing_info(e, profiler->space_parts_get_cell_id_time, + &profiler->file_space_parts_get_cell_id); + profiler_write_timing_info(e, profiler->space_count_parts_time, + &profiler->file_space_count_parts); + + /* Reset timers. */ + profiler_reset_timers(profiler); +} + +/** + * @brief Closes all output files, should be called at the end of the + * simulation. + * + * @param (return) profiler #profiler object that holds file pointers and + * function timers. + */ +void profiler_close_files(struct profiler *profiler) { + + fclose(profiler->file_engine_drift); + fclose(profiler->file_engine_rebuild); + fclose(profiler->file_scheduler_reweight); + fclose(profiler->file_scheduler_clear_waits); + fclose(profiler->file_scheduler_re_wait); + fclose(profiler->file_scheduler_enqueue); + fclose(profiler->file_engine_stats); + fclose(profiler->file_engine_launch); + fclose(profiler->file_space_rebuild); + fclose(profiler->file_engine_maketasks); + fclose(profiler->file_engine_marktasks); + fclose(profiler->file_space_regrid); + fclose(profiler->file_space_parts_sort); + fclose(profiler->file_space_split); + fclose(profiler->file_space_parts_get_cell_id); + fclose(profiler->file_space_count_parts); +} diff --git a/src/profiler.h b/src/profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..859f58ae31112a45265d84ffc6043a78514aa5ee --- /dev/null +++ b/src/profiler.h @@ -0,0 +1,84 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2016 James S. Willis (james.s.willis@durham.ac.uk) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ +#ifndef SWIFT_PROFILER_H +#define SWIFT_PROFILER_H + +/* Config parameters. */ +#include "../config.h" + +/* Includes. */ +#include "clocks.h" +#include "engine.h" +#include "hydro.h" +#include "version.h" + +/* Profiler that holds file pointers and time taken in functions. */ +struct profiler { + + /* File pointers for timing info. */ + FILE *file_engine_collect_timesteps; + FILE *file_engine_drift; + FILE *file_engine_rebuild; + FILE *file_scheduler_reweight; + FILE *file_scheduler_clear_waits; + FILE *file_scheduler_re_wait; + FILE *file_scheduler_enqueue; + FILE *file_engine_stats; + FILE *file_engine_launch; + FILE *file_space_rebuild; + FILE *file_engine_maketasks; + FILE *file_engine_marktasks; + FILE *file_space_regrid; + FILE *file_space_parts_sort; + FILE *file_space_split; + FILE *file_space_parts_get_cell_id; + FILE *file_space_count_parts; + + /* Time taken in functions. */ + ticks collect_timesteps_time; + ticks drift_time; + ticks rebuild_time; + ticks reweight_time; + ticks clear_waits_time; + ticks re_wait_time; + ticks enqueue_time; + ticks stats_time; + ticks launch_time; + ticks space_rebuild_time; + ticks engine_maketasks_time; + ticks engine_marktasks_time; + ticks space_regrid_time; + ticks space_parts_sort_time; + ticks space_split_time; + ticks space_parts_get_cell_id_time; + ticks space_count_parts_time; +}; + +/* Function prototypes. */ +void profiler_reset_timers(struct profiler *profiler); +void profiler_write_timing_info_header(struct engine *e, char *fileName, + char *functionName, FILE **file); +void profiler_write_all_timing_info_headers(struct engine *e, + struct profiler *profiler); +void profiler_write_timing_info(struct engine *e, ticks time, FILE **file); +void profiler_write_all_timing_info(struct engine *e, + struct profiler *profiler); +void profiler_close_files(struct profiler *profiler); + +#endif /* SWIFT_PROFILER_H */ diff --git a/src/swift.h b/src/swift.h index 58745f3111fc3f29490d4591ee549907392cb87e..2928c263525f57a7ee999b50547aa374b456f556 100644 --- a/src/swift.h +++ b/src/swift.h @@ -44,6 +44,7 @@ #include "partition.h" #include "physical_constants.h" #include "potential.h" +#include "profiler.h" #include "queue.h" #include "runner.h" #include "scheduler.h"