/*******************************************************************************
* 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]);
}