SMUCNGPerfOperator.cpp 14.9 KB
Newer Older
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
//================================================================================
// Name        : SMUCNGPerfOperator.cpp
// Author      : Carla Guillen
// Contact     : info@dcdb.it
// Copyright   : Leibniz Supercomputing Centre
// Description : Template implementing features to use Units in Operators.
//================================================================================

//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2018-2019 Leibniz Supercomputing Centre
//
// This program 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 2
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//================================================================================
27

28
#include "SMUCNGPerfOperator.h"
29

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/parameter/keyword.hpp>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "../../../common/include/cacheentry.h"
#include "../../../common/include/logging.h"
#include "../../../common/include/sensorbase.h"
#include "../../../common/include/timestamp.h"
#include "../../includes/QueryEngine.h"
#include "../../includes/UnitTemplate.h"
#include "SKXPMUMetrics.h"

47
SMUCNGPerfOperator::SMUCNGPerfOperator(const std::string& name): OperatorTemplate(name) {
48
    _buffers.resize(64);
49 50
}

51
SMUCNGPerfOperator::~SMUCNGPerfOperator() {
52 53
}

54
SMUCNGPerfOperator::SMUCNGPerfOperator(const SMUCNGPerfOperator& other) : OperatorTemplate(other){
55
    copy(other);
56 57 58
}

SMUCNGPerfOperator& SMUCNGPerfOperator::operator=(const SMUCNGPerfOperator& other){
Carla Guillen's avatar
Carla Guillen committed
59
    OperatorTemplate::operator =(other);
60 61 62 63 64
    copy(other);
    return *this;
}

void SMUCNGPerfOperator::copy(const SMUCNGPerfOperator& other){
Carla Guillen's avatar
Carla Guillen committed
65 66
    this->_buffers = other._buffers;
    this->_metricToPosition = other._metricToPosition;
67
    //this->_measurement_interval = other._measurement_interval;
68 69
}

70
void SMUCNGPerfOperator::printConfig(LOG_LEVEL ll) {
71 72 73
    OperatorTemplate<SMUCSensorBase>::printConfig(ll);
    LOG_VAR(ll) << " metric to position map: ";
    for(auto &kv : _metricToPosition){
74
    	LOG_VAR(ll) << "Metric = " << kv.first << " Position = " << kv.second;
75
    }
76 77
}

78
void SMUCNGPerfOperator::compute(U_Ptr unit) {
79
	auto inputs = unit->getInputs();
Carla Guillen Carias's avatar
Carla Guillen Carias committed
80
	auto timestamp = getTimestamp() - 10e9;
81
	for(auto& outSensor : unit->getOutputs()){
82
		if( outSensor->getMetric() == SMUCSensorBase::CPI) {
83
			computeCPI(inputs, outSensor, timestamp);
84
		} else if (outSensor->getMetric() == SMUCSensorBase::FREQUENCY) {
85 86 87 88 89
			computeFREQUENCY(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::FLOPS || outSensor->getMetric() == SMUCSensorBase::PACKED_FLOPS ||
				outSensor->getMetric() == SMUCSensorBase::AVX512_TOVECTORIZED_RATIO || outSensor->getMetric() == SMUCSensorBase::VECTORIZED_RATIO ||
				outSensor->getMetric() == SMUCSensorBase::SINGLE_PRECISION_TO_TOTAL_RATIO) {
			computeFLOPS(inputs, outSensor, timestamp);
Carla Guillen Carias's avatar
Carla Guillen Carias committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103
		} else if (outSensor->getMetric() == SMUCSensorBase::L3_TO_INSTRUCTIONS_RATIO){
			computeL3_TO_INSTRUCTIONS_RATIO(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::L3HIT_TO_L3MISS_RATIO ){
			computeL3HIT_TO_L3MISS_RATIO(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::LOADS_TO_STORES ){
			computeLOADS_TO_STORES(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::LOADS_TOL3MISS_RATIO ){
			computeLOADS_TOL3MISS_RATIO(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::BRANCH_PER_INSTRUCTIONS){
			computeBRANCH_PER_INSTRUCTIONS(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::MISSBRANCHES_TO_TOTAL_BRANCH_RATIO){
			computeMISSBRANCHES_TO_TOTAL_BRANCH_RATIO(inputs, outSensor, timestamp);
		} else if (outSensor->getMetric() == SMUCSensorBase::MEMORY_BANDWIDTH) {
			computeMEMORY_BANDWIDTH(inputs, outSensor, timestamp);
104
		}
Carla Guillen Carias's avatar
Carla Guillen Carias committed
105 106 107 108
		resetBuffers();
	}
}

Carla Guillen's avatar
Carla Guillen committed
109
void SMUCNGPerfOperator::query(const std::string & sensor_name, const uint64_t timestamp, vector<reading_t> &buffer){
110 111 112
	_queryEngine.querySensor(sensor_name, timestamp, timestamp, buffer, false); //use absolute timestamp and always false
}

Carla Guillen Carias's avatar
Carla Guillen Carias committed
113 114 115
void SMUCNGPerfOperator::resetBuffers(){
	for(auto &buffer: _buffers){
		buffer.clear();
116 117
	}
}
118 119 120 121 122 123 124 125

void SMUCNGPerfOperator::computeCPI(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr &outSensor, const uint64_t timestamp){
	std::vector<reading_t> & instructions = _buffers[0];
	std::vector<reading_t> & clocks = _buffers[1];
	query(inputs[_metricToPosition[SMUCSensorBase::INSTRUCTIONS]]->getName(), timestamp, instructions);
	query(inputs[_metricToPosition[SMUCSensorBase::CLOCKS]]->getName(), timestamp, clocks);
	bool wascalced = false;
	reading_t cpi;
126
	if (instructions.size() > 0 && clocks.size() > 0 && calculateMetricRatio(clocks[0], instructions[0], cpi)) {
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
		outSensor->storeReading(cpi);
	}
}

void SMUCNGPerfOperator::computeFREQUENCY(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor, const uint64_t timestamp) {
	std::vector<reading_t> & clocks = _buffers[0];
	std::vector<reading_t> & clocks_ref = _buffers[1];
	query(inputs[_metricToPosition[SMUCSensorBase::CLOCKS]]->getName(), timestamp, clocks);
	query(inputs[_metricToPosition[SMUCSensorBase::CLOCKS_REF]]->getName(), timestamp, clocks_ref);
	reading_t frequency;
	if( clocks.size() > 0 && clocks_ref.size() > 0 && calculateFrequency(clocks_ref[0],clocks[0], MIN_FREQ_MHZ, MAX_FREQ_MHZ, frequency)) {
		outSensor->storeReading(frequency);
	}
}

void SMUCNGPerfOperator::computeFLOPS(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor, const uint64_t timestamp) {
	SMUCSensorBase::Metric_t flop_metric = outSensor->getMetric();
	std::vector<reading_t> & fp_arith_scalar_double = _buffers[0];
	std::vector<reading_t> & fp_arith_scalar_single = _buffers[1];
	std::vector<reading_t> & fp_arith_128b_packed_double = _buffers[2];
	std::vector<reading_t> & fp_arith_128b_packed_single = _buffers[3];
	std::vector<reading_t> & fp_arith_256b_packed_double = _buffers[4];
	std::vector<reading_t> & fp_arith_256b_packed_single = _buffers[5];
	std::vector<reading_t> & fp_arith_512b_packed_double = _buffers[6];
	std::vector<reading_t> & fp_arith_512b_packed_single = _buffers[7];


	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_SCALAR_DOUBLE]]->getName(), timestamp, fp_arith_scalar_double);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_SCALAR_SINGLE]]->getName(), timestamp, fp_arith_scalar_single);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_128B_PACKED_DOUBLE]]->getName(), timestamp, fp_arith_128b_packed_double);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_128B_PACKED_SINGLE]]->getName(), timestamp, fp_arith_128b_packed_single);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_256B_PACKED_DOUBLE]]->getName(), timestamp, fp_arith_256b_packed_double);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_256B_PACKED_SINGLE]]->getName(), timestamp, fp_arith_256b_packed_single);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_512B_PACKED_DOUBLE]]->getName(), timestamp, fp_arith_512b_packed_double);
	query(inputs[_metricToPosition[SMUCSensorBase::FP_ARITH_512B_PACKED_SINGLE]]->getName(), timestamp, fp_arith_512b_packed_single);
	reading_t empty;
	empty.value = 0;
	empty.timestamp = 0;
	reading_t & scalar_double = fp_arith_scalar_double.size() > 0 ? fp_arith_scalar_double[0]: empty;
	reading_t & scalar_single = fp_arith_scalar_single.size() > 0 ? fp_arith_scalar_single[0]: empty;
	reading_t & packed128_double = fp_arith_128b_packed_double.size() > 0 ? fp_arith_128b_packed_double[0] : empty;
	reading_t & packed128_single = fp_arith_128b_packed_single.size() > 0 ? fp_arith_128b_packed_single[0] : empty;
	reading_t & packed256_double =  fp_arith_256b_packed_double.size() > 0 ?  fp_arith_256b_packed_double[0] : empty;
	reading_t & packed256_single = fp_arith_256b_packed_single.size() > 0 ? fp_arith_256b_packed_single[0] : empty;
	reading_t & packed512_double =  fp_arith_512b_packed_double.size() > 0 ?  fp_arith_512b_packed_double[0] :empty;
	reading_t & packed512_single = fp_arith_512b_packed_single.size() > 0 ? fp_arith_512b_packed_single[0] : empty;

	reading_t result;
	if(flop_metric == SMUCSensorBase::FLOPS) {
176
		if (calculateFlopsPerSec(scalar_double, scalar_single, packed128_double,
177
				packed128_single, packed256_double, packed256_single,
178
				packed512_double, packed512_single, result, _measuring_interval_s) ) {
179 180 181
			outSensor->storeReading(result);
		}
	} else if(flop_metric == SMUCSensorBase::PACKED_FLOPS){
182
		if(calculatePackedFlopsPerSec(packed128_double,packed128_single,packed256_double,packed256_single,packed512_double,packed512_single, result, _measuring_interval_s)){
183 184 185 186 187
			outSensor->storeReading(result);
		}
	} else if(flop_metric == SMUCSensorBase::VECTORIZED_RATIO) {
		if(calculateVectorizationRatio(scalar_double, scalar_single, packed128_double,
				packed128_single, packed256_double, packed256_single,
188
				packed512_double, packed512_single, result)) {
189 190 191 192 193
			outSensor->storeReading(result);
		}
	} else if (flop_metric == SMUCSensorBase::AVX512_TOVECTORIZED_RATIO) {
		if (calculateAVX512FlopsToVectorizedRatio(packed128_double,
				packed128_single, packed256_double, packed256_single,
194
				packed512_double, packed512_single, result )) {
195 196 197 198 199
			outSensor->storeReading(result);
		}
	} else if (flop_metric == SMUCSensorBase::SINGLE_PRECISION_TO_TOTAL_RATIO) {
		if(calculateSP_TO_TOTAL_RATIO(scalar_double, scalar_single, packed128_double,
				packed128_single, packed256_double, packed256_single,
200
				packed512_double, packed512_single, result)){
201 202 203 204 205 206 207 208 209 210 211 212 213
			outSensor->storeReading(result);
		}
	}
}



/*void SMUCNGPerfOperator::computeINSTR_INTRA_NODE_LOADIMBALANCE(std::vector<SMUCNGPtr>& inputs,
		SMUCNGPtr& outSensor, const uint64_t timestamp) {
}*/

void SMUCNGPerfOperator::computeL3_TO_INSTRUCTIONS_RATIO(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
214 215 216 217 218
	std::vector<reading_t> & l3_misses = _buffers[0];
	std::vector<reading_t> & instructions = _buffers[1];
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_LOAD_UOPS_RETIRED_L3_MISS]]->getName(), timestamp, l3_misses);
	query(inputs[_metricToPosition[SMUCSensorBase::INSTRUCTIONS]]->getName(), timestamp, instructions);
	reading_t l3toinstrRatio;
219
	if (instructions.size() > 0 && l3_misses.size() > 0 && calculateMetricRatio(instructions[0], l3_misses[0], l3toinstrRatio)) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
220 221
		outSensor->storeReading(l3toinstrRatio);
	}
222 223 224 225 226 227 228 229
}

void SMUCNGPerfOperator::computeL3_BANDWIDTH(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
}

void SMUCNGPerfOperator::computeL3HIT_TO_L3MISS_RATIO(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
230 231 232 233 234 235 236 237
	//MEM_LOAD_UOPS_RETIRED_L3_MISS/(MEM_LOAD_RETIRED_L3_HIT+MEM_LOAD_RETIRED_L3_MISS
	std::vector<reading_t> & l3_misses = _buffers[0];
	std::vector<reading_t> & l3_hits = _buffers[1];
	std::vector<reading_t> & l3_load_miss = _buffers[2];
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_LOAD_UOPS_RETIRED_L3_MISS]]->getName(), timestamp, l3_misses);
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_LOAD_RETIRED_L3_HIT]]->getName(), timestamp, l3_hits);
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_LOAD_RETIRED_L3_MISS]]->getName(), timestamp, l3_load_miss);
	reading_t l3hitToMissRatio;
238
	if (l3_misses.size() > 0 && l3_hits.size() > 0 && l3_load_miss.size() > 0 && calculateL3HitToL3MissRatio(l3_misses[0], l3_hits[0], l3_load_miss[0], l3hitToMissRatio)) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
239 240
		outSensor->storeReading(l3hitToMissRatio);
	}
241 242 243 244
}

void SMUCNGPerfOperator::computeLOADS_TO_STORES(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
245 246 247 248 249
	std::vector<reading_t> & loads = _buffers[0];
	std::vector<reading_t> & stores = _buffers[1];
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_INST_RETIRED_ALL_LOADS]]->getName(), timestamp, loads);
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_INST_RETIRED_ALL_STORES]]->getName(), timestamp, stores);
	reading_t loadToStoreRatio;
250
	if(loads.size() > 0 && stores.size() > 0 && calculateMetricRatio(loads[0], stores[0], loadToStoreRatio)){
Carla Guillen Carias's avatar
Carla Guillen Carias committed
251 252
		outSensor->storeReading(loadToStoreRatio);
	}
253 254 255 256
}

void SMUCNGPerfOperator::computeLOADS_TOL3MISS_RATIO(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
257 258 259 260 261 262
	std::vector<reading_t> & loads = _buffers[0];
	std::vector<reading_t> & l3_misses = _buffers[1];
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_INST_RETIRED_ALL_LOADS]]->getName(), timestamp, loads);
	query(inputs[_metricToPosition[SMUCSensorBase::MEM_LOAD_UOPS_RETIRED_L3_MISS]]->getName(), timestamp, l3_misses);
	reading_t loads_to_l3misses;
	if (loads.size() > 0 && l3_misses.size() > 0
263
			&& calculateMetricRatio(loads[0], l3_misses[0], loads_to_l3misses)) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
264 265
		outSensor->storeReading(loads_to_l3misses);
	}
266 267
}

Carla Guillen Carias's avatar
Carla Guillen Carias committed
268
void SMUCNGPerfOperator::computeBRANCH_PER_INSTRUCTIONS(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor, const uint64_t timestamp) {
Carla Guillen's avatar
Carla Guillen committed
269 270
	std::vector<reading_t> & missedbranches = _buffers[0];
	std::vector<reading_t> & instructions = _buffers[1];
Carla Guillen Carias's avatar
Carla Guillen Carias committed
271 272 273 274
	query(inputs[_metricToPosition[SMUCSensorBase::PERF_COUNT_HW_BRANCH_MISSES]]->getName(), timestamp, missedbranches);
	query(inputs[_metricToPosition[SMUCSensorBase::INSTRUCTIONS]]->getName(), timestamp, instructions);
	reading_t branchPerInstructions;
	if (missedbranches.size() > 0 && instructions.size() > 0
275
			&& calculateMetricRatio(missedbranches[0], instructions[0], branchPerInstructions)) {
Carla Guillen Carias's avatar
Carla Guillen Carias committed
276 277
		outSensor->storeReading(branchPerInstructions);
	}
278 279 280 281
}

void SMUCNGPerfOperator::computeMISSBRANCHES_TO_TOTAL_BRANCH_RATIO(std::vector<SMUCNGPtr>& inputs,
		SMUCNGPtr& outSensor, const uint64_t timestamp) {
Carla Guillen's avatar
Carla Guillen committed
282 283
	std::vector<reading_t> & missedbranches = _buffers[0];
	std::vector<reading_t> & totalbranches = _buffers[1];
Carla Guillen Carias's avatar
Carla Guillen Carias committed
284 285 286 287
	query(inputs[_metricToPosition[SMUCSensorBase::PERF_COUNT_HW_BRANCH_MISSES]]->getName(), timestamp, missedbranches);
	query(inputs[_metricToPosition[SMUCSensorBase::PERF_COUNT_HW_BRANCH_INSTRUCTIONS]]->getName(), timestamp, totalbranches);
	reading_t missbranchesPerTotal;
	if(missedbranches.size() > 0 && totalbranches.size() > 0 &&
288
			calculateMetricRatio(missedbranches[0], totalbranches[0], missbranchesPerTotal)){
Carla Guillen Carias's avatar
Carla Guillen Carias committed
289 290
		outSensor->storeReading(missbranchesPerTotal);
	}
291 292 293 294
}

void SMUCNGPerfOperator::computeMEMORY_BANDWIDTH(std::vector<SMUCNGPtr>& inputs, SMUCNGPtr& outSensor,
		const uint64_t timestamp) {
Carla Guillen's avatar
Carla Guillen committed
295
	std::vector<reading_t> mem_counters; //ToDo how do I get them?
296
}