compareDAGmapping.cpp 12.3 KB
Newer Older
1 2 3 4 5 6 7

// Keep in private GIT
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>
#include <thread>
8 9
#include <deque>
#include <unordered_set>
10
#include <unordered_map>
11
#include <omp.h>
12 13 14 15 16 17
using namespace std;

#include "../../Src/Utils/FGlobal.hpp"
#include "../../Src/Utils/FMath.hpp"
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FParameterNames.hpp"
18 19 20 21 22 23 24 25 26
enum TaskType {P2M = 0, M2M, M2L, M2L_OUT, L2L, L2P, P2P, P2P_OUT};
string taskNames[] = {"P2M", "M2M", "M2L", "M2L_out", "L2L", "L2P", "P2P", "P2P_out"};
struct Task
{
	TaskType type;
	long long int uniqueId;
	vector<long long int> id;
	int mpiNode;
	int level;
27
	double perf;
28 29 30 31
	bool operator==(const Task & other) const
	{
		if(type != other.type || id.size() != other.id.size())
			return false;
32 33 34 35 36 37
		//if(type == P2P_OUT) //Symétrisation
			//if(id[0] == other.id[2] && id[1] == other.id[3] && id[2] == other.id[0] && id[3] == other.id[1])
				//return true;
		//if(type == M2L_OUT) //Symétrisation
			//if(id[1] == other.id[3] && id[2] == other.id[4] && id[3] == other.id[1] && id[4] == other.id[2])
				//return true;
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52
		for(size_t i = 0; i < id.size(); ++i)
			if(id[i] != other.id[i])
				return false;
		return true;
	}
	bool operator!=(const Task & other) const
	{
		return !((*this)==other);
	}
	void print(void)
	{
		cout << taskNames[type];
		for(size_t i = 0; i < id.size(); ++i)
			cout << ", " << id[i];
53
		cout << "(mpi " << mpiNode << ")";
54 55 56 57 58 59 60 61 62 63 64 65 66
		cout << endl;
	}
};
//Spécialisation de hash pour le type Task
namespace std {
  template <> struct hash<Task>
  {
    size_t operator()(const Task & x) const
    {
		return x.uniqueId;
    }
  };
}
67 68
struct DagData
{
69
	unordered_set<Task> allTask;
70
	unordered_map<long long int, double> performence;
71
	int treeHeight;
72
};
73 74

bool parseLine(DagData & dagData, deque<string> & lineElements)
75
{
76 77 78 79 80 81 82
	if(lineElements.size() < 1)
		return false;
	Task task;
	if(lineElements.size() >= 14 && lineElements[0] == "P2P_out")
	{
		task.type = P2P_OUT;
		task.uniqueId = stoll(lineElements[1]);
83
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
84 85 86 87 88 89
		task.id.resize(4);
		task.id[0] = stoll(lineElements[9]);
		task.id[1] = stoll(lineElements[10]);
		task.id[2] = stoll(lineElements[11]);
		task.id[3] = stoll(lineElements[12]);
		task.mpiNode = stoi(lineElements[13]);
90
		task.level = dagData.treeHeight - 1;
91 92 93 94 95 96
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 10 && lineElements[0] == "P2P")
	{
		task.type = P2P;
		task.uniqueId = stoll(lineElements[1]);
97
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
98 99 100 101 102 103 104 105
		task.id.resize(4);
		task.id[0] = stoll(lineElements[5]);
		task.id[1] = stoll(lineElements[6]);
		task.id[2] = stoll(lineElements[7]);
		task.id[3] = stoll(lineElements[8]);
		if(task.id[0] == 0 && task.id[1] == 0 && task.id[2] == 0 && task.id[3] == 0)
			cout << "Suricate" << endl;
		task.mpiNode = stoi(lineElements[9]);
106
		task.level = dagData.treeHeight - 1;
107 108 109 110 111 112
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 10 && lineElements[0] == "M2L" )
	{
		task.type = M2L;
		task.uniqueId = stoll(lineElements[1]);
113
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
114 115 116 117 118 119 120
		task.id.resize(5);
		task.id[0] = stoll(lineElements[2]);
		task.id[1] = stoll(lineElements[5]);
		task.id[2] = stoll(lineElements[6]);
		task.id[3] = stoll(lineElements[7]);
		task.id[4] = stoll(lineElements[8]);
		task.mpiNode = stoi(lineElements[9]);
121
		task.level = task.id[0];
122 123 124 125 126 127
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "M2L_out")
	{
		task.type = M2L_OUT;
		task.uniqueId = stoll(lineElements[1]);
128
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
129 130 131 132 133 134 135
		task.id.resize(5);
		task.id[0] = stoll(lineElements[2]);
		task.id[1] = stoll(lineElements[8]);
		task.id[2] = stoll(lineElements[9]);
		task.id[3] = stoll(lineElements[10]);
		task.id[4] = stoll(lineElements[11]);
		task.mpiNode = stoi(lineElements[12]);
136
		task.level = task.id[0];
137 138 139 140 141 142
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "M2M")
	{
		task.type = M2M;
		task.uniqueId = stoll(lineElements[1]);
143
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
144 145 146 147 148 149 150
		task.id.resize(5);
		task.id[0] = stoll(lineElements[2]);
		task.id[1] = stoll(lineElements[8]);
		task.id[2] = stoll(lineElements[9]);
		task.id[3] = stoll(lineElements[10]);
		task.id[4] = stoll(lineElements[11]);
		task.mpiNode = stoi(lineElements[12]);
151
		task.level = task.id[0];
152 153 154 155 156 157
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "L2L")
	{
		task.type = L2L;
		task.uniqueId = stoll(lineElements[1]);
158
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
159 160 161 162 163 164 165
		task.id.resize(5);
		task.id[0] = stoll(lineElements[2]);
		task.id[1] = stoll(lineElements[8]);
		task.id[2] = stoll(lineElements[9]);
		task.id[3] = stoll(lineElements[10]);
		task.id[4] = stoll(lineElements[11]);
		task.mpiNode = stoi(lineElements[12]);
166
		task.level = task.id[0];
167 168 169 170 171 172
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 8 && lineElements[0] == "L2P")
	{
		task.type = L2P;
		task.uniqueId = stoll(lineElements[1]);
173
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
174 175 176 177
		task.id.resize(2);
		task.id[0] = stoll(lineElements[5]);
		task.id[1] = stoll(lineElements[6]);
		task.mpiNode = stoi(lineElements[7]);
178
		task.level = dagData.treeHeight - 1;
179 180 181 182 183 184
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 8 && lineElements[0] == "P2M")
	{
		task.type = L2P;
		task.uniqueId = stoll(lineElements[1]);
185
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
186 187 188 189
		task.id.resize(2);
		task.id[0] = stoll(lineElements[5]);
		task.id[1] = stoll(lineElements[6]);
		task.mpiNode = stoi(lineElements[7]);
190
		task.level = 0;
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
		dagData.allTask.insert(task);
	}
	else
	{
		cout << "No match for " << lineElements[0] << " - " << lineElements.size() << endl;
		return false;
	}
	return true;
}
void split(string& line, string const& delim, deque<string> &result)
{
	size_t prevPos = 0;
	size_t pos = 0;
	while((pos = line.find(delim, prevPos)) != string::npos)
	{
		result.push_back(line.substr(prevPos, pos-prevPos));
		prevPos = pos+delim.size();
208
	}
209 210
	if(prevPos < line.size())
		result.push_back(line.substr(prevPos));
211 212 213 214 215 216 217 218 219 220 221
}
bool fillDagData(const char* const filename, DagData & dagData)
{
	std::ifstream fichier(filename, ios::in);  // on ouvre le fichier en lecture

	if(!fichier)  // si l'ouverture a réussi
	{       
		cerr << "Couldn't open " << filename << endl;
		return false;
	}
	string line;
222 223
	string delim(", ");
	deque<string> splitLine;
224 225 226
	while(!fichier.eof())
	{
		getline(fichier, line);
227 228 229
		splitLine.clear();
		split(line, delim, splitLine);
		parseLine(dagData, splitLine);
230 231 232 233
	}
	fichier.close();  // on ferme le fichier
	return true;
}
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
bool getTaskPerf(string line, double &perf)
{
	perf = stod(line);
	return true;
}
bool getTaskId(string line, long long int & taskId)
{
	size_t pos = line.rfind('_');
	if(pos == string::npos)
		return false;
	taskId = stoll(line.substr(pos));
	return true;
}
void fillPerformanceData(const char* const filename, DagData & dagData)
{
	std::ifstream fichier(filename, ios::in);  // on ouvre le fichier en lecture

	if(!fichier)  // si l'ouverture a réussi
		cerr << "Couldn't open " << filename << endl;

	string line;
	string delim(", ");
	deque<string> splitLine;
	bool getPerf = false;
	long long int taskId;
	double perf;
	while(!fichier.eof())
	{
		getline(fichier, line);
		if(line.size() > 0 && line[0] == 'N')
		{
			if(getTaskId(line.substr(3), taskId))
				getPerf = true;
		}
		else if(getPerf && line.size() > 0 && line[0] == 'S')
		{
			if(getTaskPerf(line.substr(3), perf))
			{
				getPerf = false;;
				dagData.performence[taskId] = perf;
			}
		}
		splitLine.clear();
		split(line, delim, splitLine);
		parseLine(dagData, splitLine);
	}
	fichier.close();  // on ferme le fichier
}
282
void compareDag(DagData const& dag1, DagData const& dag2, int const treeHeight)
283
{
284
	#pragma omp parallel
285
	{
286
		#pragma omp single nowait
287
		{
288 289 290 291
			long long int notFoundCount[omp_get_num_threads()][treeHeight];
			long long int differenceMapping[omp_get_num_threads()][treeHeight];
			long long int taskCount[omp_get_num_threads()][treeHeight];
			for(int i = 0; i < omp_get_num_threads(); ++i)
292
			{
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
				for(int j = 0; j < treeHeight; ++j)
				{
					notFoundCount[i][j] = 0;
					taskCount[i][j] = 0;
					differenceMapping[i][j] = 0;
				}
			}
			for(Task task : dag1.allTask)
			{
				#pragma omp task default(shared) firstprivate(task)
				{
					bool found = false;
					Task sameTask[2];
					int sameTaskId = 0;
					if(task.level < treeHeight)
						++taskCount[omp_get_thread_num()][task.level];
					for(auto it = dag2.allTask.begin(); it != dag2.allTask.end(); ++it)
					{
						if(task == *it)
						{
							sameTask[sameTaskId++] = *it;
							found = true;
							if(sameTaskId == 2)
								break;
						}
					}
					if(found == false)
					{
						//task.print();
						if(task.level < treeHeight)
							++notFoundCount[omp_get_thread_num()][task.level];
					}
					else
					{
						bool sameNode = false;
						for(int i = 0; i < sameTaskId; ++i)
							if(sameTask[i].mpiNode == task.mpiNode)
								sameNode = true;
								
						if(!sameNode)
						{
							#pragma omp critical
							{
								task.print();
								sameTask[0].print();//Il y a au moins une tâche identique trouvée
								if(sameTaskId == 2)
									sameTask[1].print();//Il y a au moins une tâche identique trouvée
								cout << sameTaskId << endl;
								cout << endl;
							}
							if(task.level < treeHeight)
								++differenceMapping[omp_get_thread_num()][task.level];
						}
					}
				}
			}
			#pragma omp taskwait
			for(int i = 0; i < treeHeight; ++i)
			{
				long long int sum = 0;
				long long int sumDiffMapping = 0;
				long long int sumTaskCount = 0;
				for(int j = 0; j < omp_get_num_threads(); ++j)
					if(taskCount[j][i] > 0)
					{
						sum += notFoundCount[j][i];
						sumDiffMapping += differenceMapping[j][i];
						sumTaskCount += taskCount[j][i];
					}
				if(sum > 0 || sumDiffMapping > 0)
					std::cout << "Diff lvl " << i << " -> " << sum << " (Mapping error : " << sumDiffMapping << "/" << sumTaskCount << ")" << std::endl;
364 365 366
			}
		}
	}
367
}
368 369 370 371 372 373 374 375 376 377
int main(int argc, char* argv[])
{
    const FParameterNames ExplicitTrace {
        {"-E"},
        "Simgrid trace from explicit mpi"
    };
	const FParameterNames ImplicitTrace {
		{"-I"} ,
		"Simgrid trace from implicit mpi"
	};
378 379
    const FParameterNames Explicit {
        {"-e"},
380
        "Simgrid trace from explicit mpi"
381 382 383
    };
	const FParameterNames Implicit {
		{"-i"} ,
384
		"Simgrid trace from implicit mpi"
385
	};
386 387 388 389
    const FParameterNames TreeHeight {
        {"-h"},
        "Height of the tree"
    };
390
    FHelpDescribeAndExit(argc, argv, "Compare DAG mapping", Explicit, Implicit, ExplicitTrace, ImplicitTrace, TreeHeight);
391 392

    // Get params
393 394 395 396
    const char* const explicitFilename = FParameters::getStr(argc,argv,Explicit.options, "scalfmm_explicit.out");
    const char* const implicitFilename = FParameters::getStr(argc,argv,Implicit.options, "scalfmm_implicit.out");
    const char* const explicitTraceFilename = FParameters::getStr(argc,argv,Explicit.options, "explicit.rec");
    const char* const implicitTraceFilename = FParameters::getStr(argc,argv,Implicit.options, "implicit.rec");
397
    const int treeHeight = FParameters::getValue(argc,argv,TreeHeight.options, 5);
398 399 400

	DagData implicitData, explicitData;
	bool implicitGood, explicitGood;
401
	std::thread explicitThread([&](){
402
		explicitData.treeHeight = treeHeight;
403
		fillPerformanceData(explicitTraceFilename, explicitData);
404 405
		explicitGood = fillDagData(explicitFilename, explicitData);
		});
406
	std::thread implicitThread([&](){
407
		implicitData.treeHeight = treeHeight;
408
		fillPerformanceData(implicitTraceFilename, implicitData);
409 410 411
		implicitGood = fillDagData(implicitFilename, implicitData);
		});
	implicitThread.join();
412
	explicitThread.join();
413
	if(implicitGood && explicitGood)
414 415 416
	{
		cout << explicitData.allTask.size() << " tasks in explicit." << endl;
		cout << implicitData.allTask.size() << " tasks in implicit." << endl;
417
		compareDag(explicitData, implicitData, treeHeight);
418
	}
419 420
    return 0;
}