IpplMemoryUsage.cpp 4.11 KB
Newer Older
frey_m's avatar
frey_m committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
//
// Class IpplMemoryUsage
//   A simple singleton class which lets the user watch the memory consumption of a program.
//   ATTENTION: We use following memory convention
//
//              8 bit = 1 byte = 1e-3 kB = 1e-6 MB
//                             = 1e-3 / 1.024 KiB (KibiByte)
//                             = 1e-3 / 1.024 / 1.024 MiB (MebiByte)
//
//              instead of the usually taken but wrong relation 1024 kB = 1 MB.
//
//   General usage
//   1) create the instance using IpplMemoryUsage::getInstance(unit, reset).
//      The reset boolean indicates wether the memory at creation should be
//      subtracted from the measurements later on.
//      The class is based on t getrusage() that returns the memory
//      consumption in kB (KiloByte). You can specify the return value of
//      IpplMemoryUsage by the first argument.
//      Although one can use those input parameters they are only applied
//      at the first call. Additional calls with different input do NOT
//      modify the instance.
//   2) At any point in the program you can call IpplMemoryUsage::sample()
//      to collect the data.
//
// Copyright (c) 2017 - 2018, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// Implemented as part of the PhD thesis
// "Precise Simulations of Multibunches in High Intensity Cyclotrons"
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
gsell's avatar
gsell committed
41 42
#include "Utility/IpplMemoryUsage.h"

frey_m's avatar
frey_m committed
43 44 45
//////////////////////////////////////////////////////////////////////
IpplMemoryUsage::IpplMemoryUsage()
{ }
gsell's avatar
gsell committed
46 47


frey_m's avatar
frey_m committed
48 49 50 51
IpplMemoryUsage::IpplMemoryUsage(Unit unit, bool reset)
    : who_m(RUSAGE_SELF)
{
    globalMemPerCore_m = std::unique_ptr<double[]>(new double[Ippl::getNodes()]);
gsell's avatar
gsell committed
52
    
frey_m's avatar
frey_m committed
53 54 55 56
    switch ( unit ) {
        case Unit::BIT:
            conversion_factor_m = 8.0e3;
            unit_m = "bit";
57
            break;
frey_m's avatar
frey_m committed
58 59 60
        case Unit::B:
            conversion_factor_m = 1.0e3;
            unit_m = "B";
61
            break;
frey_m's avatar
frey_m committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
        case Unit::KB:
            conversion_factor_m = 1.0;
            unit_m = "kB";
            break;
        case Unit::KiB:
            conversion_factor_m = 1.0 / 1.024;
            unit_m = "KiB";
            break;
        case Unit::MB:
            conversion_factor_m = 1.0e-3;
            unit_m = "MB";
            break;
        case Unit::MiB:
            conversion_factor_m = 1.0 / (1.024 * 1024.0);
            unit_m = "MiB";
            break;
        case Unit::GiB:
            conversion_factor_m = 1.0 / (1.024 * 1024.0 * 1024.0);
            unit_m = "GiB";
            break;
        case Unit::GB:
        default:
            conversion_factor_m = 1.0e-6;
            unit_m = "GB";
            break;
    }
gsell's avatar
gsell committed
88
    
frey_m's avatar
frey_m committed
89 90 91 92 93
    initial_memory_m = 0.0;
    if ( reset ) {
        this->sample_m();
        initial_memory_m = max_rss_m;
    }
gsell's avatar
gsell committed
94 95 96
}


frey_m's avatar
frey_m committed
97 98 99 100 101
IpplMemoryUsage::IpplMemory_p IpplMemoryUsage::getInstance(Unit unit,
                                                           bool reset)
{
    static IpplMemory_t instance_mp = IpplMemory_t(new IpplMemoryUsage(unit, reset));
    return instance_mp.get();
gsell's avatar
gsell committed
102 103 104
}


frey_m's avatar
frey_m committed
105 106
double IpplMemoryUsage::getMemoryUsage(int core) const {
    return globalMemPerCore_m[core];
gsell's avatar
gsell committed
107 108 109
}


frey_m's avatar
frey_m committed
110 111 112
void IpplMemoryUsage::sample() {
    // update max_rss_m
    this->sample_m();
gsell's avatar
gsell committed
113
    
frey_m's avatar
frey_m committed
114
    for(int i = 0; i < Ippl::getNodes(); i++)
frey_m's avatar
frey_m committed
115 116 117
        globalMemPerCore_m[i] = 0;
    
    double localMemPerCore = max_rss_m;
frey_m's avatar
frey_m committed
118
    
frey_m's avatar
frey_m committed
119
    gather(&localMemPerCore, &globalMemPerCore_m[0], 1);
gsell's avatar
gsell committed
120 121 122
}


frey_m's avatar
frey_m committed
123 124
const std::string& IpplMemoryUsage::getUnit() const {
    return unit_m;
gsell's avatar
gsell committed
125 126 127
}


frey_m's avatar
frey_m committed
128 129 130 131 132 133 134 135
void IpplMemoryUsage::sample_m() {
    rusage usage;
    if ( getrusage(who_m, &usage) == -1 )
        throw std::runtime_error(
            "IpplMemoryUsage::sample_m(): Error in collecting memory!");
    
    max_rss_m = usage.ru_maxrss * conversion_factor_m - initial_memory_m;
}