meric.cpp 9.69 KB
Newer Older
Ondrej Meca's avatar
Ondrej Meca committed
1
2
3
4
5

#include "meric.h"

using namespace meric;

6
int         Meric::ITERATION  = mutils::getenv("MERIC_ITERATION", 0);
7
int         Meric::MODE       = mutils::getenv<int>("MERIC_MODE" , MODE_RUN);
Ondrej Meca's avatar
Ondrej Meca committed
8
9
bool        Meric::CONTINUAL  = mutils::getenv("MERIC_CONTINUAL" , false);
bool        Meric::DETAILED   = mutils::getenv("MERIC_DETAILED"  , false);
10
bool        Meric::AGGREGATE  = mutils::getenv("MERIC_AGGREGATE" , true);
Ondrej Meca's avatar
Ondrej Meca committed
11
bool        Meric::DEBUG      = mutils::getenv("MERIC_DEBUG"     , false);
12
bool        Meric::SAMPLES    = mutils::getenv("MERIC_SAMPLES"   , false);
13
bool        Meric::HDF5       = mutils::getenv("MERIC_HDF5"      , true);
Ondrej Vysocky's avatar
Ondrej Vysocky committed
14
std::string Meric::COUNTERS   = mutils::getenv("MERIC_COUNTERS"  , std::string("none"));
15
std::string Meric::BARRIERS   = mutils::getenv("MERIC_BARRIERS"  , std::string("all"));
16
std::string Meric::OUTPUT_DIR = mutils::getenv("MERIC_OUTPUT_DIR", std::string("mericMeasurement"));
17
std::string Meric::REGION_OPTIONS  = mutils::getenv("MERIC_REGION_OPTIONS", std::string(""));
Ondrej Meca's avatar
Ondrej Meca committed
18

19
20
21
std::map<std::string, std::map<std::pair<int, int>, struct RegionParameters > > Meric::parameter;
RegionParameters Meric::ignoreSettings = {};
std::vector <std::string> Meric::ignoreRegions;
22
std::vector<std::string> Meric::_name;
xvysoc01's avatar
xvysoc01 committed
23
std::vector<int> Meric::_stack;
Ondrej Meca's avatar
Ondrej Meca committed
24
RegionParameters Meric::defaultParameter;
25
SocketsRegionParameters Meric::currentState;
26
std::string Meric::_mainRegion;
27
28
timespec Meric::_startTime;
timespec Meric::_stopTime;
29
bool Meric::IGNORE = false;
30
31
bool Meric::MPIbarriers = true;
bool Meric::OMPbarriers = true;
32
33
std::string Meric::outputFilenameInfo = "";
std::string Meric::OUTPUT_FILENAME = "";
Ondrej Meca's avatar
Ondrej Meca committed
34

35

Ondrej Meca's avatar
Ondrej Meca committed
36
37
void Meric::readRegionParameters()
{
38
39
40
41
42
43
44
45
46
47
48
49
	if (getDefaultParameters())
		exit(1);

	if (! Meric::REGION_OPTIONS.empty())
		readRegionOptions();
}

int Meric::getDefaultParameters()
{
	int ret=0;
//OBLIGATORY SECTION
	defaultParameter.nthreads        = mutils::getenv("MERIC_NUM_THREADS", -1);
50
51
	defaultParameter.frequency       = mutils::frequencyToHz(mutils::getenv("MERIC_FREQUENCY", std::string("")));
	defaultParameter.uncoreFrequency = mutils::frequencyToHz(mutils::getenv("MERIC_UNCORE_FREQUENCY", std::string("")));
xvysoc01's avatar
ENH #22    
xvysoc01 committed
52

53
#if defined (HAVE_CPUFREQ_H) || defined (HAVE_X86_ADAPT_H) || defined (HAVE_MSR_DORE_H)
54
	if (defaultParameter.frequency < 0)
xvysoc01's avatar
ENH #22    
xvysoc01 committed
55
	{
Ondrej Vysocky's avatar
Ondrej Vysocky committed
56
		std::cerr << "MERIC ERROR: set MERIC_FREQUENCY [Hz]\n";
57
		ret = 1;
xvysoc01's avatar
ENH #22    
xvysoc01 committed
58
	}
59
60
61
62
	else if (defaultParameter.frequency != 0)
	{
		Meric::outputFilenameInfo +="CF_";
	}
63
	
xvysoc01's avatar
ENH #22    
xvysoc01 committed
64
65
#endif

66
#if defined (HAVE_X86_ADAPT_H) || defined (HAVE_MSR_CORE_H)
67
	if (defaultParameter.uncoreFrequency < 0)
68
	{
Ondrej Vysocky's avatar
Ondrej Vysocky committed
69
		std::cerr << "MERIC ERROR: set MERIC_UNCORE_FREQUENCY [Hz]\n";
70
		ret = 1;
71
	}
72
73
74
75
	else if (defaultParameter.uncoreFrequency != 0)
	{
		Meric::outputFilenameInfo +="UnCF_";
	}
xvysoc01's avatar
ENH #22    
xvysoc01 committed
76
#endif
77
78
79
80
81
82
83
84

#ifdef HAVE_OMP_H
	if (defaultParameter.nthreads < 0)
	{
		std::cerr << "MERIC ERROR: set MERIC_NUM_THREADS\n"
				  << "MERIC INFO: if the application doesn't use openMP, export MERIC_NUM_THREADS=0\n";
		ret = 1;
	}
85
86
87
88
	else if (defaultParameter.nthreads != 0)
	{
		Meric::outputFilenameInfo +="thrds_";
	}
xvysoc01's avatar
ENH #22    
xvysoc01 committed
89
#endif
90

91
92
93
94
#ifndef HAVE_HDF5_H
	Meric::HDF5 = false;
#endif 

95
96
97
98
	if (ret)
		return ret;

//OPTIONAL SECTION
99
	MERIC_INFO << "Default number of threads: " << defaultParameter.nthreads << "\n";
Ondrej Meca's avatar
Ondrej Meca committed
100
	MERIC_INFO << "Default frequency: " << defaultParameter.frequency << "\n";
xvysoc01's avatar
xvysoc01 committed
101
	MERIC_INFO << "Default uncore frequency: " << defaultParameter.uncoreFrequency << "\n";
Ondrej Vysocky's avatar
Ondrej Vysocky committed
102

103
104
105
	std::string outputFilenameSuffix = mutils::getenv("MERIC_OUTPUT_FILENAME", "");
	if (outputFilenameSuffix.size() == 0)
	{
106
		if (Meric::outputFilenameInfo.size() == 0)
107
108
109
110
111
112
113
114
115
116
117
		{
			Meric::OUTPUT_FILENAME = "log";
			Meric::outputFilenameInfo = "CFG";
		}
		else
		{
			Meric::outputFilenameInfo.pop_back();
		}
	}
	else
	{
118
		for (size_t i = 0; i < std::count(outputFilenameSuffix.begin(), outputFilenameSuffix.end(), '_')+1; i++)
119
120
121
122
123
124
125
126
127
128
		{
			Meric::outputFilenameInfo +="APP"+std::to_string(i)+"_";
		}
		if (Meric::outputFilenameInfo.size() > 0) //remove the last underscore
		{
			Meric::outputFilenameInfo.pop_back();
		}
		Meric::OUTPUT_FILENAME += outputFilenameSuffix;
	}
	
129
	if (Meric::MODE < MODE_HDEEM || Meric::MODE >= MODE_LIMIT)
130
	{
131
132
		std::cerr << "MERIC WARNING: MERIC MODE unknown value <"<<MODE_HDEEM<<","<<MODE_LIMIT-1<<"> - default "<< MODE_RUN <<std::endl;
		Meric::MODE = MODE_RUN;
133
134
	}
	
135
	if (Meric::BARRIERS != "all")
136
137
138
139
	{
		if (Meric::BARRIERS == "mpi")
		{
			Meric::OMPbarriers = false;
140
			std::cerr << "MERIC WARNING: OpenMP BARRIERS turned off\n";
141
142
143
144
		}
		else if (Meric::BARRIERS == "omp")
		{
			Meric::MPIbarriers = false;
145
			std::cerr << "MERIC WARNING: MPI BARRIERS turned off\n";
146
147
148
149
150
		}
		else if (Meric::BARRIERS == "none")
		{
			Meric::OMPbarriers = false;
			Meric::MPIbarriers = false;
151
			std::cerr << "MERIC WARNING: BARRIERS turned off\n";
152
153
154
		}
	}
	
Ondrej Vysocky's avatar
Ondrej Vysocky committed
155
156
	if (Meric::COUNTERS != "none")
	{
157
		if (Meric::COUNTERS != "papi" && Meric::COUNTERS != "perfevent")
Ondrej Vysocky's avatar
Ondrej Vysocky committed
158
		{
159
160
			if (Meric::COUNTERS != "")
				std::cerr << "MERIC WARNING: unknown counter type "<<Meric::COUNTERS<<std::endl;
Ondrej Vysocky's avatar
Ondrej Vysocky committed
161
162
163
			Meric::COUNTERS = "none";
		}
	}
164

165
166
	return 0;
}
167

168
169
170
171
172
173
174
void Meric::readRegionOptions()
{
//load input file
	std::string line, jsonString = "";
	std::ifstream jsonFile (Meric::REGION_OPTIONS);

	if (jsonFile.is_open())
175
	{
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
		while (getline(jsonFile,line))
		{
			jsonString += " " + line;
		}
		jsonFile.close();
	}
	const char * json = jsonString.c_str();

// parse input json
	struct json_value_s* root = json_parse(json, strlen(json));
	if (root ==  NULL)
	{
		std::cerr << "MERIC ERROR: empty or invalid input json\n";
		return;
	}

	struct json_object_element_s* data = ((struct json_object_s*)root->payload)->start;
	if (data == NULL)
	{
		free(root);
		return;
	}

//	process the settings into a structure
	struct json_object_element_s* region;
	struct json_object_element_s* node;
	struct json_object_element_s* socket;
203
	
204
205
206
207
208
209
210
	do
	{
		if (data->name->string[0] != '@')	//region
		{
			parameter[std::string(data->name->string)][std::make_pair(-1, -1)] = getRegionSettings(data);
		}
		else if (std::string(data->name->string) == "@IGNORE")
211
		{
212
213
214
			MERIC_INFO << data->name->string <<"\n";
			struct json_object_element_s* ignore = ((struct json_object_s*)data->value->payload)->start;
			do
215
			{
216
				if (std::string(ignore->name->string) == "@REGIONS")
217
				{
218
219
220
221
222
223
224
					struct json_array_element_s* set = ((struct json_array_s*)ignore->value->payload)->start;
					do
					{
						MERIC_INFO << "\t" << ((struct json_string_s*)set->value->payload)->string << std::endl;
						ignoreRegions.push_back(std::string(((struct json_string_s*)set->value->payload)->string));
						set = set->next;
					}while(set != NULL);
225
				}
226
				else if (std::string(ignore->name->string) == "@CHANGE")
227
				{
228
					ignoreSettings = getRegionSettings(ignore);
229
				}
230
231
232
233
234
235
236
237
238
239
240
241
242
				ignore = ignore->next;
			}while(ignore != NULL);
		}
		else if(std::string(data->name->string) == "@NODE")
		{
			MERIC_INFO << data->name->string <<"\n";
			node = ((struct json_object_s*)data->value->payload)->start;

			do{
				//list of regions
				struct json_object_element_s* socketOrRegion = ((struct json_object_s*)node->value->payload)->start;
				do{
					if(std::string(socketOrRegion->name->string) == "@SOCKET")
243
					{
244
245
246
247
248
249
250
251
252
253
						socket = ((struct json_object_s*)socketOrRegion->value->payload)->start;
						do{
							//list of regions
							region = ((struct json_object_s*)socket->value->payload)->start;
							do{
								parameter[std::string(region->name->string)][std::make_pair(std::stoi(std::string(node->name->string)), std::stoi(std::string(socket->name->string)))] = getRegionSettings(region);
								region = region->next;
							}while (region != NULL);
							socket = socket->next;
						}while (socket != NULL);
Ondrej Meca's avatar
Ondrej Meca committed
254
					}
255
					else	//list of regions
256
					{
257
						parameter[std::string(socketOrRegion->name->string)][std::make_pair(std::stoi(std::string(node->name->string)), -1)] = getRegionSettings(socketOrRegion);
xvysoc01's avatar
xvysoc01 committed
258
					}
259
260
					socketOrRegion = socketOrRegion->next;
				}while (socketOrRegion != NULL);
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
				node = node->next;
			}while(node != NULL);

		}
		else if(std::string(data->name->string) == "@SOCKET")
		{
			std::cerr << data->name->string <<"\n";
			socket = ((struct json_object_s*)data->value->payload)->start;
			do{
				//list of regions
				region = ((struct json_object_s*)socket->value->payload)->start;
				do{
					parameter[std::string(region->name->string)][std::make_pair(-1, std::stoi(std::string(socket->name->string)))] = getRegionSettings(region);
					region = region->next;
				}while (region != NULL);
				socket = socket->next;
			}while(socket != NULL);
		}
		data = data->next;

	}while(data != NULL);

/*
//print the parameters (core frequency only)
	for ( const auto &regs : parameter )
	{
		for(const auto & pair : parameter[regs.first])	
		{
			MERIC_INFO << regs.first << "\n"
				<< "\t" << pair.first.first << ":" << pair.first.second<< "\n"
				<< "\t" << pair.second.frequency << "\n\n";
Ondrej Meca's avatar
Ondrej Meca committed
293
294
		}
	}
295
296
*/
	free(root);
Ondrej Meca's avatar
Ondrej Meca committed
297
}
Ondrej Meca's avatar
Ondrej Meca committed
298

299
300
301
302
303
304
305
306
RegionParameters Meric::getRegionSettings(json_object_element_s * data)
{
	RegionParameters param = {};
	struct json_object_element_s* set = ((struct json_object_s*)data->value->payload)->start;
	
	do
	{
		if ("FREQUENCY" == std::string(set->name->string))
307
308
		{
			if (defaultParameter.frequency != 0)
309
				param.frequency = mutils::frequencyToHz(std::string(((struct json_string_s*)set->value->payload)->string));
310
		}
311
		else if ("UNCORE_FREQUENCY" == std::string(set->name->string))
312
313
		{
			if (defaultParameter.uncoreFrequency != 0)
314
				param.uncoreFrequency = mutils::frequencyToHz(std::string(((struct json_string_s*)set->value->payload)->string));
315
		}
316
		else if ("NUM_THREADS" == std::string(set->name->string))
317
318
		{
			if (defaultParameter.nthreads != 0)
319
				param.nthreads = std::stoi(std::string(((struct json_string_s*)set->value->payload)->string));
320
		}
321
		else
322
			std::cerr << "MERIC ERROR: invalid region options key - " << set->name->string << std::endl;
323
324
325
326
327
		set = set->next;
	}while (set != NULL);
	
	return param;
}