Skip to content

Commit

Permalink
Add memory usage diagnostic Postprocessor (idaholab#8619)
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen committed Mar 7, 2017
1 parent 742af5a commit 6572c9f
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 0 deletions.
64 changes: 64 additions & 0 deletions 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<MemoryUsage>();

/**
* 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
2 changes: 2 additions & 0 deletions framework/src/base/Moose.C
Expand Up @@ -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"
Expand Down Expand Up @@ -629,6 +630,7 @@ registerObjects(Factory & factory)
registerPostprocessor(TimestepSize);
registerPostprocessor(RunTime);
registerPostprocessor(PerformanceData);
registerPostprocessor(MemoryUsage);
registerPostprocessor(NumElems);
registerPostprocessor(NumNodes);
registerPostprocessor(NumNonlinearIterations);
Expand Down
144 changes: 144 additions & 0 deletions 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 <array>
#include <unistd.h>

#ifdef __APPLE__
#include <mach/task.h>
#include <mach/clock.h>
#include <mach/mach.h>
#endif

template<>
InputParameters validParams<MemoryUsage>()
{
InputParameters params = validParams<GeneralPostprocessor>();
MooseEnum mem_type("virtual_memory physical_memory page_faults", "virtual_memory");
params.addParam<MooseEnum>("mem_type", mem_type, "Memory metric to report.");
MooseEnum value_type("total average max_process min_processs", "total");
params.addParam<MooseEnum>("value_type", value_type, "Aggregation method to apply to the requested memory metric.");
params.addParam<bool>("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<MooseEnum>("mem_type").getEnum<MemType>()),
_value_type(getParam<MooseEnum>("value_type").getEnum<ValueType>()),
_report_peak_value(getParam<bool>("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<unsigned long, 21> 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<task_info_t>(&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
101 changes: 101 additions & 0 deletions 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
[]
7 changes: 7 additions & 0 deletions 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
[../]
[]

0 comments on commit 6572c9f

Please sign in to comment.