| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 | /* StarPU --- Runtime system for heterogeneous multicore architectures. * * Copyright (C) 2011-2020  Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria * Copyright (C) 2011       Télécom-SudParis * Copyright (C) 2020       Federal University of Rio Grande do Sul (UFRGS) * * StarPU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * StarPU 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 Lesser General Public License in COPYING.LGPL for more details. */#if !defined(_WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)#include <dirent.h>#include <sys/stat.h>#endif#include <config.h>#include <assert.h>#include <getopt.h>#include <unistd.h>#include <stdio.h>#include <starpu.h>#include <common/utils.h>#include <common/uthash.h>#include <core/perfmodel/perfmodel.h> // we need to browse the list associated to history-based models                                      // just like in starpu_perfmodel_plot#define STRHEADCMP(s, head) strncmp(s, head, strlen(head))#if defined(_WIN32) && !defined(__CYGWIN__)#include <windows.h>#endif#define PROGNAME "starpu_perfmodel_recdump"struct _footprint_list{	struct _footprint_list* next;	uint32_t footprint;};struct _footprint_list* add_footprint(struct _footprint_list* list, uint32_t footprint){	struct _footprint_list * l = list;	while(l)	{		if(l->footprint == footprint) break;		l = l->next;	}	if(l) return list;	else	{		struct _footprint_list * res = malloc(sizeof(struct _footprint_list));		res->footprint = footprint;		res->next = list;		return res;	}}static struct model{	UT_hash_handle hh;	char *name;	struct starpu_perfmodel model;	struct _footprint_list* footprints;} *models;void get_comb_name(int comb, char* name, int name_size){	struct starpu_perfmodel_arch *arch_comb = starpu_perfmodel_arch_comb_fetch(comb);	STARPU_ASSERT_MSG(arch_comb->ndevices == 1, "Cannot work with multi-device workers\n");	snprintf(name, name_size, "%s%d", starpu_perfmodel_get_archtype_name(arch_comb->devices[0].type), arch_comb->devices[0].devid);}void print_archs(FILE* output){	int nb_workers = 0;	unsigned workerid, node, src, dst; int comb, old_comb = -1;	fprintf(output, "%%rec: worker_count\n\n");	for (workerid = 0; workerid < starpu_worker_get_count(); workerid++)	{		struct starpu_perfmodel_arch* arch = starpu_worker_get_perf_archtype(workerid, STARPU_NMAX_SCHED_CTXS);		comb = starpu_perfmodel_arch_comb_get(arch->ndevices, arch->devices);		STARPU_ASSERT(comb >= 0);		if(comb != old_comb)		{			if(nb_workers > 0)			{				char name[32];				get_comb_name(old_comb, name, 32);				fprintf(output, "Architecture: %s\n", name);				fprintf(output, "NbWorkers: %d\n\n", nb_workers);			}			old_comb = comb;			nb_workers = 1;		}		else		{			nb_workers += 1;		}	}	if(nb_workers > 0)	{		char name[32];		get_comb_name(old_comb, name, 32);		fprintf(output, "Architecture: %s\n", name);		fprintf(output, "NbWorkers: %d\n\n", nb_workers);	}	fprintf(output, "%%rec: memory_workers\n\n");	for (node = 0; node < starpu_memory_nodes_get_count(); node++)	{		unsigned printed = 0;		char name[32];		fprintf(output, "MemoryNode: %u\n", node);		starpu_memory_node_get_name(node, name, sizeof(name));		fprintf(output, "Name: %s\n", name);		fprintf(output, "Size: %ld\n", (long) starpu_memory_get_total(node));		for (workerid = 0; workerid < starpu_worker_get_count(); workerid++)		{			if (starpu_worker_get_memory_node(workerid) == node)			{				if (!printed)				{					fprintf(output, "Workers:");					printed = 1;				}				fprintf(output, " %u", workerid);			}		}		if (printed)			fprintf(output, "\n");		fprintf(output, "\n");	}	fprintf(output, "%%rec: memory_performance\n\n");	for (src = 0; src < starpu_memory_nodes_get_count(); src++)	{		for (dst = 0; dst < starpu_memory_nodes_get_count(); dst++)		{			if (src != dst)			{				fprintf(output, "MemoryNodeSrc: %u\n", src);				fprintf(output, "MemoryNodeDst: %u\n", dst);				fprintf(output, "Bandwidth: %f\n", starpu_transfer_bandwidth(src, dst));				fprintf(output, "Latency: %f\n", starpu_transfer_latency(src, dst));				fprintf(output, "\n");			}		}	}}/* output file name */static char* poutput = NULL;static char* pinput = NULL;static void usage(){	fprintf(stderr, "Dumps perfmodels to a rec file\n\n");	fprintf(stderr, "Usage: %s [ input-file ] [ -o output-file ]\n", PROGNAME);        fprintf(stderr, "\n");	fprintf(stderr, "If input or output file names are not given, stdin and stdout are used.");	fprintf(stderr, "\n");        fprintf(stderr, "Report bugs to <"PACKAGE_BUGREPORT">.");        fprintf(stderr, "\n");}static void print_entry(const char *name, const char *archname, FILE *output, struct starpu_perfmodel_history_entry *entry){	fprintf(output, "Model: %s\n", name);	fprintf(output, "Architecture: %s\n", archname);	fprintf(output, "Footprint: %08x\n", entry->footprint);	fprintf(output, "Size: %lu\n", (unsigned long) entry->size);	if (!isnan(entry->flops))		fprintf(output, "Flops: %-15e\n", entry->flops);	fprintf(output, "Mean: %-15e\nStddev: %-15e\n",		entry->mean, entry->deviation);	fprintf(output, "Samples: %u\n", entry->nsample);	fprintf(output, "\n");}static void parse_args(int argc, char **argv){	int c;	static struct option long_options[] =	{		{"help",      no_argument, NULL, 'h'},		{"output",     required_argument, NULL, 'o'},		{0, 0, 0, 0}	};	int option_index;	while ((c = getopt_long(argc, argv, "ho:", long_options, &option_index)) != -1)	{		switch (c)		{                case 'h': /* display help */		  usage();		  exit(EXIT_SUCCESS);		  break;		case 'o':		  poutput = optarg;		  break;		case '?':		default:			fprintf(stderr, "Unrecognized option: -%c\n", optopt);		}	}	if(optind < argc)	{		pinput = argv[optind++];		if(optind < argc)		{			fprintf(stderr, "Unrecognized argument: %s\n", argv[optind]);			exit(EXIT_FAILURE);		}	}}int main(int argc, char **argv){#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)	WSADATA wsadata;	WSAStartup(MAKEWORD(1,0), &wsadata);	_STARPU_MSG("Listing perfmodels is not implemented on pure Windows yet\n");	return 1;#else	FILE* output;	parse_args(argc, argv);	if(poutput != NULL)	{		output = fopen(poutput, "w+");		if (!output)		{			fprintf(stderr, "couldn't open %s for write: %s\n", poutput, strerror(errno));			exit(EXIT_FAILURE);		}	}	else	{		output = stdout;	}	if (starpu_init(NULL) != 0)	{		fprintf(stderr, "StarPU initialization failure\n");		exit(EXIT_FAILURE);	}	starpu_pause();	if(pinput)	{		FILE* input = fopen(pinput, "r");		char s[1024], *c;		struct model *model, *tmp=NULL;		uint32_t footprint = 0;		char *model_name = NULL;		int ret;		if (!input)		{			fprintf(stderr, "couldn't open %s for read: %s\n", pinput, strerror(errno));			exit(EXIT_FAILURE);		}		while (fgets(s, sizeof(s), input))		{			if (strlen(s) == sizeof(s) - 1)			{				fprintf(stderr, "oops, very long line '%s', it's odd\n", s);				exit(EXIT_FAILURE);			}			if (s[0] == '\n')			{				/* empty line, end of task */				if (model_name)				{					/* Try to get already-loaded model */					HASH_FIND_STR(models, model_name, model);					if (model == NULL)					{						model = malloc(sizeof(*model));						model->name = model_name;						model->footprints = NULL;						memset(&model->model, 0, sizeof(model->model));						model->model.type = STARPU_PERFMODEL_INVALID;						ret = starpu_perfmodel_load_symbol(model_name, &model->model);						if (ret == 1)						{							fprintf(stderr, "The performance model for the symbol <%s> could not be loaded\n", model_name);							exit(EXIT_FAILURE);						}						HASH_ADD_STR(models, name, model);					}					else					{						free(model_name);					}					model->footprints = add_footprint(model->footprints, footprint);					model_name = NULL;				}				continue;			}			/* Get rec field name */			c = strchr(s, ':');			if (!c)			{				fprintf(stderr, "odd line '%s'\n", s);				exit(EXIT_FAILURE);			}			if (!STRHEADCMP(s, "Footprint: "))			{				footprint = strtoul(s + strlen("Footprint: "), NULL, 16);			}			else if (!STRHEADCMP(s, "Model: "))			{				model_name = strdup(s + strlen("Model: "));				model_name[strlen(model_name) - 1] = '\0'; /* Drop '\n' */			}		}		/* All models loaded */		{			print_archs(output);			fprintf(output, "%%rec: timing\n\n");			int nb_combs = starpu_perfmodel_get_narch_combs();			HASH_ITER(hh, models, model, tmp)			{				struct _footprint_list* l = model->footprints, *ltmp;				int comb;				while(l)				{					for(comb = 0; comb < nb_combs; comb++)					{						char archname[32];						get_comb_name(comb, archname, 32);						if(!model->model.state || model->model.state->nimpls[comb] == 0)						{							_STARPU_DISP("Symbol %s does not have any implementation on comb %d, not dumping\n", model->name, comb);							continue;						}						if(model->model.state->nimpls[comb] > 1)							_STARPU_DISP("Warning, more than one implementations in comb %d of symbol %s, using only the first one\n", comb, model->name);						struct starpu_perfmodel_per_arch *arch_model = &model->model.state->per_arch[comb][0];						struct starpu_perfmodel_history_list *ptr;						ptr = arch_model->list;						if(!ptr)							_STARPU_DISP("Implementation %d of symbol %s does not have history based model, not dumping\n", comb,  model->name);						else while(ptr)						     {							     struct starpu_perfmodel_history_entry *entry = ptr->entry;							     if(entry->footprint == l->footprint)							     {								     print_entry(model->name, archname, output, entry);								     break;							     }							     ptr=ptr->next;						     }					}					ltmp = l->next;					free(l);					l = ltmp;				}				free(model->name);				HASH_DEL(models, model);			}		}		fclose(input);	}	else	{		fprintf(output, "%%rec: timing\n\n");		char *path;		DIR *dp;		struct dirent *ep;		path = _starpu_get_perf_model_dir_codelet();		dp = opendir(path);		if (dp != NULL)		{			while ((ep = readdir(dp)))			{				if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, ".."))				{					int comb, nb_combs;					char* symbol = strdup(ep->d_name);					char *dot = strrchr(symbol, '.');					struct starpu_perfmodel model = {.type = STARPU_PERFMODEL_INVALID };					if(dot) *dot = '\0';					if (starpu_perfmodel_load_symbol(symbol, &model) != 0)					{						free(symbol);						continue;					}					if(model.state == NULL)					{						free(symbol);						continue;					}					_STARPU_DISP("Dumping %s\n", symbol);					nb_combs = starpu_perfmodel_get_narch_combs();					for(comb = 0; comb < nb_combs; ++comb)					{						char name[32];						get_comb_name(comb, name, 32);						if(!model.state || model.state->nimpls[comb] == 0)						{							_STARPU_DISP("Symbol %s does not have any implementation on comb %d, not dumping\n", symbol, comb);							fprintf(output, "\n");							continue;						}						struct starpu_perfmodel_per_arch *arch_model = &model.state->per_arch[comb][0];						struct starpu_perfmodel_history_list *ptr;						ptr = arch_model->list;						if(!ptr)							_STARPU_DISP("Symbol %s for comb %d does not have history based model, not dumping\n", symbol,  comb);						else while(ptr)						     {							     print_entry(symbol, name, output, ptr->entry);							     ptr=ptr->next;						     }					}					starpu_perfmodel_unload_model(&model);					free(symbol);				}			}			closedir (dp);		}		else		{			_STARPU_DISP("Could not open the perfmodel directory <%s>: %s\n", path, strerror(errno));		}		print_archs(output);	}	starpu_resume();	starpu_shutdown();	fclose(output);	return 0;#endif}
 |