/******************************************************************************* * 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 . * ******************************************************************************/ /* Config parameters. */ #include /* Some standard headers. */ #include #include /* This object's header. */ #include "profiler.h" /* Local includes */ #include "clocks.h" #include "hydro.h" #include "version.h" /* Array to store the list of file names. Order must match profiler_types * enumerator and profiler_func_names. */ const char *profiler_file_names[profiler_length] = {"enginecollecttimesteps", "enginedrift", "enginerebuild", "schedulerreweight", "schedulerclearwaits", "schedulerrewait", "schedulerenqueue", "engineprintstats", "enginelaunch", "spacerebuild", "enginemaketasks", "enginemarktasks", "spaceregrid", "spacepartssort", "spacesplit", "spacegetcellid", "spacecountparts"}; /* Array to store the list of function names. Order must match profiler_types * enumerator and profiler_file_names. */ const char *profiler_func_names[profiler_length] = {"engine_collect_timesteps", "engine_drift", "engine_rebuild", "scheduler_reweight", "scheduler_clear_waits", "scheduler_rewait", "scheduler_enqueue", "engine_print_stats", "engine_launch", "space_rebuild", "engine_maketasks", "engine_marktasks", "space_regrid", "space_parts_sort", "space_split", "space_get_cell_id", "space_count_parts"}; /** * @brief Resets all timers. * * @param profiler #profiler object that holds file pointers and * function timers. */ void profiler_reset_timers(struct profiler *profiler) { /* Iterate over times array and reset values. */ for (int i = 0; i < profiler_length; i++) profiler->times[i] = 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 file (return) pointer used to open output file. */ void profiler_write_timing_info_header(const struct engine *e, const char *fileName, const 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"); if (*file == NULL) error("Could not create file '%s'.", fullFileName); 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 %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", "s-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 profiler #profiler object that holds file pointers and * function timers. */ void profiler_write_all_timing_info_headers(const struct engine *e, struct profiler *profiler) { /* Iterate over files array and write file headers. */ for (int i = 0; i < profiler_length; i++) { profiler_write_timing_info_header( e, profiler_file_names[i], profiler_func_names[i], &profiler->files[i]); } } /** * @brief Writes timing info to the output file. * * @param e #engine object to get various properties. * @param time Time in ticks to be written to the output file. * @param file pointer used to open output file. */ void profiler_write_timing_info(const struct engine *e, ticks time, FILE *file) { fprintf(file, " %6d %14e %14e %10lld %10lld %10lld %21.3f\n", e->step, e->time, e->time_step, e->updates, e->g_updates, e->s_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 profiler #profiler object that holds file pointers and * function timers. */ void profiler_write_all_timing_info(const struct engine *e, struct profiler *profiler) { /* Iterate over times array and print timing info to files. */ for (int i = 0; i < profiler_length; i++) { profiler_write_timing_info(e, profiler->times[i], profiler->files[i]); } /* Reset timers. */ profiler_reset_timers(profiler); } /** * @brief Closes all output files, should be called at the end of the * simulation. * * @param profiler #profiler object that holds file pointers and * function timers. */ void profiler_close_files(struct profiler *profiler) { /* Iterate over files array and close files. */ for (int i = 0; i < profiler_length; i++) fclose(profiler->files[i]); }