From 6572c9f02597774e23befe074aee4ad5533b7dc8 Mon Sep 17 00:00:00 2001 From: Daniel Schwen Date: Thu, 23 Feb 2017 12:09:47 -0700 Subject: [PATCH] Add memory usage diagnostic Postprocessor (#8619) --- .../include/postprocessors/MemoryUsage.h | 64 ++++++++ framework/src/base/Moose.C | 2 + framework/src/postprocessors/MemoryUsage.C | 144 ++++++++++++++++++ .../memory_usage/print_memory_usage.i | 101 ++++++++++++ test/tests/postprocessors/memory_usage/tests | 7 + 5 files changed, 318 insertions(+) create mode 100644 framework/include/postprocessors/MemoryUsage.h create mode 100644 framework/src/postprocessors/MemoryUsage.C create mode 100644 test/tests/postprocessors/memory_usage/print_memory_usage.i create mode 100644 test/tests/postprocessors/memory_usage/tests diff --git a/framework/include/postprocessors/MemoryUsage.h b/framework/include/postprocessors/MemoryUsage.h new file mode 100644 index 000000000000..7fc02d4ee5e9 --- /dev/null +++ b/framework/include/postprocessors/MemoryUsage.h @@ -0,0 +1,64 @@ +/****************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MOOSE - Multiphysics Object Oriented Simulation Environment */ +/* */ +/* (c) 2010 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/* */ +/* Prepared by Battelle Energy Alliance, LLC */ +/* Under Contract No. DE-AC07-05ID14517 */ +/* With the U. S. Department of Energy */ +/* */ +/* See COPYRIGHT for full restrictions */ +/****************************************************************/ + +#ifndef MEMORYUSAGE_H +#define MEMORYUSAGE_H + +#include "GeneralPostprocessor.h" + +class MemoryUsage; + +template<> +InputParameters validParams(); + +/** + * Output maximum, average, or total process memory usage + */ +class MemoryUsage : public GeneralPostprocessor +{ +public: + MemoryUsage(const InputParameters & parameters); + + virtual void timestepSetup() override; + + virtual void initialize() override; + virtual void execute() override; + virtual void finalize() override; + virtual PostprocessorValue getValue() override; + +protected: + enum class MemType { + virtual_memory, + physical_memory, + page_faults + } _mem_type; + + enum class ValueType { + total, + average, + max_process, + min_process + } _value_type; + + /// memory usage metric in bytes + Real _value; + + /// peak memory usage metric in bytes (of multiple samples in the current time step) + Real _peak_value; + + /// report peak value for multiple samples in a time step + const bool _report_peak_value; +}; + +#endif // MEMORYUSAGE_H diff --git a/framework/src/base/Moose.C b/framework/src/base/Moose.C index 912fd10b194b..01dc24df99ee 100644 --- a/framework/src/base/Moose.C +++ b/framework/src/base/Moose.C @@ -193,6 +193,7 @@ #include "TimestepSize.h" #include "RunTime.h" #include "PerformanceData.h" +#include "MemoryUsage.h" #include "NumElems.h" #include "NumNodes.h" #include "NumNonlinearIterations.h" @@ -629,6 +630,7 @@ registerObjects(Factory & factory) registerPostprocessor(TimestepSize); registerPostprocessor(RunTime); registerPostprocessor(PerformanceData); + registerPostprocessor(MemoryUsage); registerPostprocessor(NumElems); registerPostprocessor(NumNodes); registerPostprocessor(NumNonlinearIterations); diff --git a/framework/src/postprocessors/MemoryUsage.C b/framework/src/postprocessors/MemoryUsage.C new file mode 100644 index 000000000000..e396aa0902a5 --- /dev/null +++ b/framework/src/postprocessors/MemoryUsage.C @@ -0,0 +1,144 @@ +/****************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MOOSE - Multiphysics Object Oriented Simulation Environment */ +/* */ +/* (c) 2010 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/* */ +/* Prepared by Battelle Energy Alliance, LLC */ +/* Under Contract No. DE-AC07-05ID14517 */ +/* With the U. S. Department of Energy */ +/* */ +/* See COPYRIGHT for full restrictions */ +/****************************************************************/ + +#include "MemoryUsage.h" + +#include +#include + +#ifdef __APPLE__ +#include +#include +#include +#endif + +template<> +InputParameters validParams() +{ + InputParameters params = validParams(); + MooseEnum mem_type("virtual_memory physical_memory page_faults", "virtual_memory"); + params.addParam("mem_type", mem_type, "Memory metric to report."); + MooseEnum value_type("total average max_process min_processs", "total"); + params.addParam("value_type", value_type, "Aggregation method to apply to the requested memory metric."); + params.addParam("report_peak_value", true, "If the postprocessor is executed more than one during a time step, report the aggregated peak value."); + return params; +} + +MemoryUsage::MemoryUsage(const InputParameters & parameters) : + GeneralPostprocessor(parameters), + _mem_type(getParam("mem_type").getEnum()), + _value_type(getParam("value_type").getEnum()), + _report_peak_value(getParam("report_peak_value")) +{ +} + +void +MemoryUsage::timestepSetup() +{ + _peak_value = 0.0; +} + +void +MemoryUsage::initialize() +{ + _value = 0.0; +} + +void +MemoryUsage::execute() +{ + // inspect /proc + std::ifstream stat_stream("/proc/self/stat", std::ios_base::in); + std::array val; + if (stat_stream) + { + // if the proc filesystem file is found (Linux) read its contents + std::string pid, comm, state; + stat_stream >> pid >> comm >> state; + for (unsigned int i = 0; i < 21; ++i) + stat_stream >> val[i]; + + // resident size is reported as number of pages in /proc + val[20] *= sysconf(_SC_PAGE_SIZE); + } + else + { + // set all data entries to zero (if all else should fail) + val.fill(0); + + // obtain mach task info on mac OS +#ifdef __APPLE__ + struct task_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + if (KERN_SUCCESS == task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast(&t_info), &t_info_count)) + { + val[19] = t_info.virtual_size; + val[20] = t_info.resident_size; + } +#endif + } + + // get the requested per core metric + switch (_mem_type) + { + case MemType::virtual_memory: + _value = val[19]; + break; + + case MemType::physical_memory: + _value = val[20]; + break; + + case MemType::page_faults: + // major page faults are currently only reported on Linux systems + _value = val[8]; + break; + } +} + +void +MemoryUsage::finalize() +{ + // perform the requested reduction + switch (_value_type) + { + case ValueType::total: + gatherSum(_value); + break; + + case ValueType::average: + gatherSum(_value); + _value /= n_processors(); + break; + + case ValueType::max_process: + gatherMax(_value); + break; + + case ValueType::min_process: + gatherMin(_value); + break; + } + + if (_value > _peak_value) + _peak_value = _value; +} + +PostprocessorValue +MemoryUsage::getValue() +{ + return _report_peak_value ? _peak_value : _value; +} + +#undef RUSAGE_AVAILABLE diff --git a/test/tests/postprocessors/memory_usage/print_memory_usage.i b/test/tests/postprocessors/memory_usage/print_memory_usage.i new file mode 100644 index 000000000000..1ea1535e509f --- /dev/null +++ b/test/tests/postprocessors/memory_usage/print_memory_usage.i @@ -0,0 +1,101 @@ +[Mesh] + type = GeneratedMesh + dim = 2 + nx = 2 + ny = 2 +[] + +[Variables] + [./u] + [../] +[] + +[Kernels] + [./diff] + type = Diffusion + variable = u + [../] + [./dt] + type = TimeDerivative + variable = u + [../] +[] + +[BCs] + [./left] + type = DirichletBC + variable = u + boundary = left + value = 0 + [../] + [./right] + type = DirichletBC + variable = u + boundary = right + value = 1 + [../] +[] + +[Adaptivity] + [./Markers] + [./uni] + type = UniformMarker + mark = REFINE + [../] + [../] + marker = uni + stop_time = 7.5 +[] + +[Postprocessors] + [./physical] + type = MemoryUsage + mem_type = physical_memory + value_type = total + execute_on = 'initial TIMESTEP_END nonlinear linear' + [../] + [./virtual] + type = MemoryUsage + mem_type = virtual_memory + value_type = total + execute_on = 'initial TIMESTEP_END' + [../] + [./page_faults] + type = MemoryUsage + mem_type = page_faults + value_type = total + execute_on = 'initial TIMESTEP_END' + [../] + [./DOFs] + type = NumDOFs + execute_on = 'initial TIMESTEP_END' + [../] + [./walltime] + type = PerformanceData + event = ALIVE + execute_on = 'initial TIMESTEP_END' + [../] +[] + +[Executioner] + type = Transient + + #solve_type = 'PJFNK' + #petsc_options_iname = '-pc_type -pc_hypre_type' + #petsc_options_value = 'hypre boomeramg' + + solve_type = 'NEWTON' + petsc_options_iname = '-pc_type' + petsc_options_value = 'lu' + + nl_abs_tol = 1e-10 + + num_steps = 8 + dt = 1 +[] + +[Outputs] + csv = true + execute_on = 'INITIAL TIMESTEP_END FINAL' + print_perf_log = true +[] diff --git a/test/tests/postprocessors/memory_usage/tests b/test/tests/postprocessors/memory_usage/tests new file mode 100644 index 000000000000..9a23c37699ad --- /dev/null +++ b/test/tests/postprocessors/memory_usage/tests @@ -0,0 +1,7 @@ +[Tests] + [./print_memory_usage] + type = CheckFiles + input = print_memory_usage.i + check_files = print_memory_usage_out.csv + [../] +[]