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

// Keep in private GIT
#include <iostream>
#include <fstream>
#include <vector>
#include <regex>
#include <thread>
Martin Khannouz's avatar
Martin Khannouz committed
8 9
#include <deque>
#include <unordered_set>
10
#include <unordered_map>
11
#include <omp.h>
12 13
using namespace std;

14 15 16 17
#include "Utils/FGlobal.hpp"
#include "Utils/FMath.hpp"
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
Martin Khannouz's avatar
Martin Khannouz committed
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;
Martin Khannouz's avatar
Martin Khannouz committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
	bool operator==(const Task & other) const
	{
		if(type != other.type || id.size() != other.id.size())
			return false;
		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];
46
		cout << "(mpi " << mpiNode << ")";
Martin Khannouz's avatar
Martin Khannouz committed
47 48 49 50 51 52 53 54 55 56 57 58 59
		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;
    }
  };
}
60 61
struct DagData
{
Martin Khannouz's avatar
Martin Khannouz committed
62
	unordered_set<Task> allTask;
63
	unordered_map<long long int, double> performence;
64
	int treeHeight;
65
};
Martin Khannouz's avatar
Martin Khannouz committed
66 67

bool parseLine(DagData & dagData, deque<string> & lineElements)
68
{
Martin Khannouz's avatar
Martin Khannouz committed
69 70 71 72 73 74 75
	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]);
76
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
77 78 79 80 81 82
		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]);
83
		task.level = dagData.treeHeight - 1;
Martin Khannouz's avatar
Martin Khannouz committed
84 85 86 87 88 89
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 10 && lineElements[0] == "P2P")
	{
		task.type = P2P;
		task.uniqueId = stoll(lineElements[1]);
90
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
91 92 93 94 95 96
		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]);
		task.mpiNode = stoi(lineElements[9]);
97
		task.level = dagData.treeHeight - 1;
Martin Khannouz's avatar
Martin Khannouz committed
98 99 100 101 102 103
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 10 && lineElements[0] == "M2L" )
	{
		task.type = M2L;
		task.uniqueId = stoll(lineElements[1]);
104
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
105 106 107 108 109 110 111
		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]);
112
		task.level = (int)task.id[0];
Martin Khannouz's avatar
Martin Khannouz committed
113 114 115 116 117 118
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "M2L_out")
	{
		task.type = M2L_OUT;
		task.uniqueId = stoll(lineElements[1]);
119
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
120 121 122 123 124 125 126
		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]);
127
		task.level = (int)task.id[0];
Martin Khannouz's avatar
Martin Khannouz committed
128 129 130 131 132 133
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "M2M")
	{
		task.type = M2M;
		task.uniqueId = stoll(lineElements[1]);
134
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
135 136 137 138 139 140 141
		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]);
142
		task.level = (int)task.id[0];
Martin Khannouz's avatar
Martin Khannouz committed
143 144 145 146 147 148
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 13 && lineElements[0] == "L2L")
	{
		task.type = L2L;
		task.uniqueId = stoll(lineElements[1]);
149
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
150 151 152 153 154 155 156
		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]);
157
		task.level = (int)task.id[0];
Martin Khannouz's avatar
Martin Khannouz committed
158 159 160 161 162 163
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 8 && lineElements[0] == "L2P")
	{
		task.type = L2P;
		task.uniqueId = stoll(lineElements[1]);
164
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
165 166 167 168
		task.id.resize(2);
		task.id[0] = stoll(lineElements[5]);
		task.id[1] = stoll(lineElements[6]);
		task.mpiNode = stoi(lineElements[7]);
169
		task.level = dagData.treeHeight - 1;
Martin Khannouz's avatar
Martin Khannouz committed
170 171 172 173 174 175
		dagData.allTask.insert(task);
	}
	else if(lineElements.size() >= 8 && lineElements[0] == "P2M")
	{
		task.type = L2P;
		task.uniqueId = stoll(lineElements[1]);
176
		task.perf = dagData.performence.count(task.uniqueId) == 1 ? dagData.performence[task.uniqueId] : 0.0;
Martin Khannouz's avatar
Martin Khannouz committed
177 178 179 180
		task.id.resize(2);
		task.id[0] = stoll(lineElements[5]);
		task.id[1] = stoll(lineElements[6]);
		task.mpiNode = stoi(lineElements[7]);
181
		task.level = 0;
Martin Khannouz's avatar
Martin Khannouz committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
		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();
199
	}
Martin Khannouz's avatar
Martin Khannouz committed
200 201
	if(prevPos < line.size())
		result.push_back(line.substr(prevPos));
202 203 204 205 206 207 208 209 210 211 212
}
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;
Martin Khannouz's avatar
Martin Khannouz committed
213 214
	string delim(", ");
	deque<string> splitLine;
215 216 217
	while(!fichier.eof())
	{
		getline(fichier, line);
Martin Khannouz's avatar
Martin Khannouz committed
218 219 220
		splitLine.clear();
		split(line, delim, splitLine);
		parseLine(dagData, splitLine);
221 222 223 224
	}
	fichier.close();  // on ferme le fichier
	return true;
}
225 226 227 228 229 230 231 232 233 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
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
}
273
void compareDag(DagData const& dag1, DagData const& dag2, int const treeHeight)
274
{
275
	#pragma omp parallel
Martin Khannouz's avatar
Martin Khannouz committed
276
	{
277
		#pragma omp single nowait
Martin Khannouz's avatar
Martin Khannouz committed
278
		{
279 280 281 282
			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)
Martin Khannouz's avatar
Martin Khannouz committed
283
			{
284 285 286 287 288 289 290 291 292 293 294 295 296 297
				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;
298
					//Count task per level
299 300
					if(task.level < treeHeight)
						++taskCount[omp_get_thread_num()][task.level];
301 302
					//Look into the second dag to find task in it
					//We look for two task because it may be symetrized
303 304 305 306 307 308 309 310 311 312
					for(auto it = dag2.allTask.begin(); it != dag2.allTask.end(); ++it)
					{
						if(task == *it)
						{
							sameTask[sameTaskId++] = *it;
							found = true;
							if(sameTaskId == 2)
								break;
						}
					}
313
					//If the task it not found, print it and count it
314 315
					if(found == false)
					{
316 317
						#pragma omp critical
						task.print();
318 319 320
						if(task.level < treeHeight)
							++notFoundCount[omp_get_thread_num()][task.level];
					}
321
					else //else check the mapping
322 323 324 325 326
					{
						bool sameNode = false;
						for(int i = 0; i < sameTaskId; ++i)
							if(sameTask[i].mpiNode == task.mpiNode)
								sameNode = true;
327
						//The tasks are not mapped on the same node	
328 329 330 331 332 333 334
						if(!sameNode)
							if(task.level < treeHeight)
								++differenceMapping[omp_get_thread_num()][task.level];
					}
				}
			}
			#pragma omp taskwait
335
			//Sum results by level and print it
336 337 338 339 340 341 342 343 344 345 346 347
			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];
					}
348
				//Print only if there is error repported on the level
349 350
				if(sum > 0 || sumDiffMapping > 0)
					std::cout << "Diff lvl " << i << " -> " << sum << " (Mapping error : " << sumDiffMapping << "/" << sumTaskCount << ")" << std::endl;
Martin Khannouz's avatar
Martin Khannouz committed
351 352 353
			}
		}
	}
354
}
355 356 357 358 359 360 361 362 363 364
int main(int argc, char* argv[])
{
    const FParameterNames ExplicitTrace {
        {"-E"},
        "Simgrid trace from explicit mpi"
    };
	const FParameterNames ImplicitTrace {
		{"-I"} ,
		"Simgrid trace from implicit mpi"
	};
365 366
    const FParameterNames Explicit {
        {"-e"},
367
        "Simgrid trace from explicit mpi"
368 369 370
    };
	const FParameterNames Implicit {
		{"-i"} ,
371
		"Simgrid trace from implicit mpi"
372
	};
Martin Khannouz's avatar
Martin Khannouz committed
373 374 375 376
    const FParameterNames TreeHeight {
        {"-h"},
        "Height of the tree"
    };
377
    FHelpDescribeAndExit(argc, argv, "Compare DAG mapping", Explicit, Implicit, ExplicitTrace, ImplicitTrace, TreeHeight);
378 379

    // Get params
380 381
    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");
Martin Khannouz's avatar
Martin Khannouz committed
382
    const int treeHeight = FParameters::getValue(argc,argv,TreeHeight.options, 5);
383 384 385

	DagData implicitData, explicitData;
	bool implicitGood, explicitGood;
386
	//Read data from files and put it into the DAG data structure
Martin Khannouz's avatar
Martin Khannouz committed
387
	std::thread explicitThread([&](){
388
		explicitData.treeHeight = treeHeight;
389 390
		explicitGood = fillDagData(explicitFilename, explicitData);
		});
Martin Khannouz's avatar
Martin Khannouz committed
391
	std::thread implicitThread([&](){
392
		implicitData.treeHeight = treeHeight;
393 394 395
		implicitGood = fillDagData(implicitFilename, implicitData);
		});
	implicitThread.join();
396
	explicitThread.join();
397
	//If every thing went good, start comparing
398
	if(implicitGood && explicitGood)
Martin Khannouz's avatar
Martin Khannouz committed
399 400 401
	{
		cout << explicitData.allTask.size() << " tasks in explicit." << endl;
		cout << implicitData.allTask.size() << " tasks in implicit." << endl;
402
		//compareDag(implicitData, explicitData, treeHeight);
403
		compareDag(explicitData, implicitData, treeHeight);
Martin Khannouz's avatar
Martin Khannouz committed
404
	}
405 406
    return 0;
}