Browse Source

Add support for PAPI counters

Lucas Leandro Nesi 5 years ago
parent
commit
0e3afa3cb7

+ 6 - 2
configure.ac

@@ -1,7 +1,7 @@
 # StarPU --- Runtime system for heterogeneous multicore architectures.
 #
 # Copyright (C) 2011-2018                                Inria
-# Copyright (C) 2009-2019                                Université de Bordeaux
+# Copyright (C) 2009-2020                                Université de Bordeaux
 # Copyright (C) 2017                                     Guillaume Beauchamp
 # Copyright (C) 2018                                     Federal University of Rio Grande do Sul (UFRGS)
 # Copyright (C) 2018                                     Umeà University
@@ -2142,6 +2142,10 @@ if test x$use_fxt = xyes; then
 		FXT_LIBS="$(pkg-config --variable=libdir fxt)/libfxt.a -Wl,--as-needed $(pkg-config --libs --static fxt) -Wl,--no-as-needed"
 	fi
 
+	AC_CHECK_LIB([papi], [PAPI_library_init],
+		     [AC_DEFINE([STARPU_PAPI], [1], [Define to 1 if you have the libpapi library])
+		      PAPI_LIBS=-lpapi])
+
 	##########################################
 	# Poti is a library to generate paje trace files
 	##########################################
@@ -3450,7 +3454,7 @@ AM_CONDITIONAL(AVAILABLE_DOC, [test x$available_doc != xno])
 ###############################################################################
 
 # these are the flags needed for linking libstarpu (and thus also for static linking)
-LIBSTARPU_LDFLAGS="$STARPU_OPENCL_LDFLAGS $STARPU_CUDA_LDFLAGS $HWLOC_LIBS $FXT_LIBS $STARPU_COI_LDFLAGS $STARPU_SCIF_LDFLAGS $STARPU_RCCE_LDFLAGS $STARPU_LEVELDB_LDFLAGS $STARPU_GLPK_LDFLAGS $STARPU_LEVELDB_LDFLAGS $SIMGRID_LIBS $STARPU_BLAS_LDFLAGS $STARPU_OMP_LDFLAGS $DGELS_LIBS"
+LIBSTARPU_LDFLAGS="$STARPU_OPENCL_LDFLAGS $STARPU_CUDA_LDFLAGS $HWLOC_LIBS $FXT_LIBS $PAPI_LIBS $STARPU_COI_LDFLAGS $STARPU_SCIF_LDFLAGS $STARPU_RCCE_LDFLAGS $STARPU_LEVELDB_LDFLAGS $STARPU_GLPK_LDFLAGS $STARPU_LEVELDB_LDFLAGS $SIMGRID_LIBS $STARPU_BLAS_LDFLAGS $STARPU_OMP_LDFLAGS $DGELS_LIBS"
 AC_SUBST([LIBSTARPU_LDFLAGS])
 
 LIBSTARPU_LINK=libstarpu-$STARPU_EFFECTIVE_VERSION.la

+ 1 - 0
include/starpu_config.h.in

@@ -77,6 +77,7 @@
 #undef STARPU_OPENGL_RENDER
 #undef STARPU_USE_GTK
 #undef STARPU_HAVE_X11
+#undef STARPU_PAPI
 
 #undef STARPU_HAVE_POSIX_MEMALIGN
 

+ 1 - 0
include/starpu_fxt.h

@@ -65,6 +65,7 @@ struct starpu_fxt_options
 	char *dag_path;
 	char *tasks_path;
 	char *data_path;
+	char *papi_path;
 	char *comms_path;
 	char *anim_path;
 	char *states_path;

+ 13 - 0
include/starpu_profiling.h

@@ -23,6 +23,12 @@
 #include <errno.h>
 #include <time.h>
 
+#include <starpu_config.h>
+
+#ifdef STARPU_PAPI
+#include <papi.h>
+#endif
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -91,6 +97,13 @@ struct starpu_profiling_task_info
 	uint64_t stall_cycles;
 	/** Energy consumed by the task, in Joules */
 	double energy_consumed;
+
+#ifdef STARPU_PAPI
+	/** PAPI Events **/
+	long long int papi_values[PAPI_MAX_HWCTRS];
+	int papi_event_set;
+#endif
+
 };
 
 /**

+ 6 - 0
src/common/fxt.h

@@ -258,6 +258,8 @@
 #define _STARPU_FUT_KEYMASK_HYP            FUT_KEYMASK18
 #define _STARPU_FUT_KEYMASK_HYP_VERBOSE    FUT_KEYMASK19
 
+#define _STARPU_FUT_PAPI_TASK_EVENT_VALUE   0x5186
+
 extern unsigned long _starpu_job_cnt;
 
 static inline unsigned long _starpu_fxt_get_job_id(void)
@@ -980,6 +982,9 @@ do {										\
 #define _STARPU_TRACE_END_WRITEBACK_ASYNC(memnode)		\
 	FUT_FULL_PROBE2(_STARPU_FUT_KEYMASK_DSM_VERBOSE, _STARPU_FUT_END_WRITEBACK_ASYNC, memnode, _starpu_gettid());
 
+#define _STARPU_TRACE_PAPI_TASK_EVENT(event_id, task, value)	\
+	FUT_DO_PROBE3(_STARPU_FUT_PAPI_TASK_EVENT_VALUE, event_id, _starpu_get_job_associated_to_task(task)->job_id, value)
+
 /* We skip these events becasue they are called so often that they cause FxT to
  * fail and make the overall trace unreadable anyway. */
 #define _STARPU_TRACE_START_PROGRESS(memnode)		\
@@ -1366,6 +1371,7 @@ do {										\
 #define _STARPU_TRACE_DATA_STATE_OWNER(handle, node)	do {(void)(handle); (void)(node);} while(0)
 #define _STARPU_TRACE_DATA_STATE_SHARED(handle, node)	do {(void)(handle); (void)(node);} while(0)
 #define _STARPU_TRACE_DATA_REQUEST_CREATED(handle, orig, dest, prio, is_pre) do {(void)(handle); (void)(orig); (void)(dest); (void)(prio); (void)(is_pre);} while(0)
+#define _STARPU_TRACE_PAPI_TASK_EVENT(event_id, task, value) do {(void)(event_id); (void)(task); (void)(value);} while(0)
 
 #endif // STARPU_USE_FXT
 

+ 51 - 0
src/debug/traces/starpu_fxt.c

@@ -30,6 +30,10 @@
 #endif
 #define STARPU_TRACE_STR_LEN 200
 
+#ifdef STARPU_PAPI
+#include <papi.h>
+#endif
+
 #ifdef STARPU_USE_FXT
 #include "starpu_fxt.h"
 #include <inttypes.h>
@@ -81,6 +85,7 @@ static FILE *activity_file;
 static FILE *anim_file;
 static FILE *tasks_file;
 static FILE *data_file;
+static FILE *papi_file;
 static FILE *trace_file;
 static FILE *comms_file;
 
@@ -327,6 +332,25 @@ static struct data_info *get_data(unsigned long handle, int mpi_rank)
 	return data;
 }
 
+static void handle_papi_event(struct fxt_ev_64 *ev, struct starpu_fxt_options *options)
+{
+#ifdef STARPU_PAPI
+	int event_code = ev->param[0];
+	unsigned long task = ev->param[1];
+	long long int value = ev->param[2];
+	//char *prefix = options->file_prefix;
+
+	if (papi_file){
+		char event_str[PAPI_MAX_STR_LEN];
+		PAPI_event_code_to_name(event_code, event_str);
+		fprintf(papi_file, "JobId: %lu\n", task);
+		fprintf(papi_file, "Event: %s\n", event_str);
+		fprintf(papi_file, "Value: %lld\n", value);
+		fprintf(papi_file, "\n");
+	}
+#endif
+}
+
 static void data_dump(struct data_info *data)
 {
 	if (!data_file)
@@ -3685,6 +3709,10 @@ void _starpu_fxt_parse_new_file(char *filename_in, struct starpu_fxt_options *op
                                        handle_memnode_event_start_4(&ev, options, "rc");
                                }
                                break;
+
+		  case _STARPU_FUT_PAPI_TASK_EVENT_VALUE:
+				handle_papi_event(&ev, options);
+				break;
 			case _STARPU_FUT_DATA_COPY:
 				if (!options->no_bus)
 				     handle_data_copy();
@@ -4167,6 +4195,7 @@ void starpu_fxt_options_init(struct starpu_fxt_options *options)
 	options->tasks_path = "tasks.rec";
 	options->comms_path = "comms.rec";
 	options->data_path = "data.rec";
+	options->papi_path = "papi.rec";
 	options->anim_path = "trace.html";
 	options->states_path = "trace.rec";
 	options->distrib_time_path = "distrib.data";
@@ -4252,6 +4281,17 @@ void _starpu_fxt_comms_file_init(struct starpu_fxt_options *options)
 }
 
 static
+void _starpu_fxt_papi_file_init(struct starpu_fxt_options *options)
+{
+#ifdef STARPU_PAPI
+	if (options->papi_path)
+		papi_file = fopen(options->papi_path, "w+");
+	else
+		papi_file = NULL;
+#endif
+}
+
+static
 void _starpu_fxt_write_trace_header(FILE *f)
 {
 	fprintf(f, "#\n");
@@ -4318,6 +4358,15 @@ void _starpu_fxt_data_file_close(void)
 }
 
 static
+void _starpu_fxt_papi_file_close(void)
+{
+#ifdef STARPU_PAPI
+	if (papi_file)
+		fclose(papi_file);
+#endif
+}
+
+static
 void _starpu_fxt_trace_file_close(void)
 {
 	if (trace_file)
@@ -4417,6 +4466,7 @@ void starpu_fxt_generate_trace(struct starpu_fxt_options *options)
 	_starpu_fxt_anim_file_init(options);
 	_starpu_fxt_tasks_file_init(options);
 	_starpu_fxt_data_file_init(options);
+	_starpu_fxt_papi_file_init(options);
 	_starpu_fxt_comms_file_init(options);
 	_starpu_fxt_trace_file_init(options);
 
@@ -4548,6 +4598,7 @@ void starpu_fxt_generate_trace(struct starpu_fxt_options *options)
 	_starpu_fxt_anim_file_close();
 	_starpu_fxt_tasks_file_close();
 	_starpu_fxt_data_file_close();
+	_starpu_fxt_papi_file_close();
 	_starpu_fxt_comms_file_close();
 	_starpu_fxt_trace_file_close();
 

+ 7 - 1
src/drivers/cpu/driver_cpu.c

@@ -1,7 +1,7 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
  * Copyright (C) 2011,2012,2014-2017,2019                 Inria
- * Copyright (C) 2008-2019                                Université de Bordeaux
+ * Copyright (C) 2008-2020                                Université de Bordeaux
  * Copyright (C) 2010                                     Mehdi Juhoor
  * Copyright (C) 2010-2017,2019                           CNRS
  * Copyright (C) 2013                                     Thibaut Lambert
@@ -111,7 +111,13 @@ static int execute_job_on_cpu(struct _starpu_job *j, struct starpu_task *worker_
 			else
 				_starpu_simgrid_submit_job(cpu_args->workerid, j, perf_arch, NAN, NULL);
 #else
+#  ifdef STARPU_PAPI
+			_starpu_profiling_papi_task_start_counters(task);
+#  endif
 			func(_STARPU_TASK_GET_INTERFACES(task), task->cl_arg);
+#  ifdef STARPU_PAPI
+			_starpu_profiling_papi_task_stop_counters(task);
+#  endif
 #endif
 			_STARPU_TRACE_END_EXECUTING();
 		}

+ 81 - 0
src/profiling/profiling.c

@@ -26,6 +26,10 @@
 #include <common/fxt.h>
 #include <errno.h>
 
+#ifdef STARPU_PAPI
+#include <papi.h>
+#endif
+
 static struct starpu_profiling_worker_info worker_info[STARPU_NMAXWORKERS];
 /* TODO: rather use rwlock */
 static starpu_pthread_mutex_t worker_info_mutex[STARPU_NMAXWORKERS];
@@ -38,6 +42,10 @@ static struct timespec sleeping_start_date[STARPU_NMAXWORKERS];
 static unsigned worker_registered_executing_start[STARPU_NMAXWORKERS];
 static struct timespec executing_start_date[STARPU_NMAXWORKERS];
 
+#ifdef STARPU_PAPI
+static int papi_events[PAPI_MAX_HWCTRS];
+static int papi_nevents = 0;
+#endif
 
 /* Store the busid of the different (src, dst) pairs. busid_matrix[src][dst]
  * contains the busid of (src, dst) or -1 if the bus was not registered. */
@@ -133,8 +141,81 @@ void _starpu_profiling_init(void)
 	{
 		STARPU_PTHREAD_MUTEX_INIT(&worker_info_mutex[worker], NULL);
 	}
+
+#ifdef STARPU_PAPI
+		int retval = PAPI_library_init(PAPI_VER_CURRENT);
+		if (retval != PAPI_VER_CURRENT)
+		{
+			 _STARPU_MSG("Failed init PAPI, error: %s.\n", PAPI_strerror(retval));
+		}
+		retval = PAPI_thread_init(pthread_self);
+		if (retval != PAPI_OK)
+		{
+			 _STARPU_MSG("Failed init PAPI thread, error: %s.\n", PAPI_strerror(retval));
+		}
+
+		char *conf_papi_events;
+		char *papi_event_name;
+		conf_papi_events = starpu_getenv("STARPU_PROF_PAPI_EVENTS");
+		if (conf_papi_events != NULL)
+		{
+			while ((papi_event_name = strtok_r(conf_papi_events, " ", &conf_papi_events)))
+			{
+				_STARPU_DEBUG("Loading PAPI Event:%s\n", papi_event_name);
+				retval = PAPI_event_name_to_code ((char*)papi_event_name, &papi_events[papi_nevents]);
+				if (retval != PAPI_OK)
+				      _STARPU_MSG("Failed to codify papi event [%s], error: %s.\n", papi_event_name, PAPI_strerror(retval));
+				else
+					papi_nevents++;
+			}
+		}
+#endif
+
 }
 
+#ifdef STARPU_PAPI
+void _starpu_profiling_papi_task_start_counters(struct starpu_task *task)
+{
+	if (!starpu_profiling_status_get())
+		return;
+
+	struct starpu_profiling_task_info *profiling_info;
+	profiling_info = task->profiling_info;
+	if (profiling_info)
+	{
+		profiling_info->papi_event_set = PAPI_NULL;
+		PAPI_create_eventset(&profiling_info->papi_event_set);
+		for(int i=0; i<papi_nevents; i++)
+		{
+			PAPI_add_event(profiling_info->papi_event_set, papi_events[i]);
+			profiling_info->papi_values[i]=0;
+		}
+		PAPI_reset(profiling_info->papi_event_set);
+		PAPI_start(profiling_info->papi_event_set);
+	}
+}
+
+void _starpu_profiling_papi_task_stop_counters(struct starpu_task *task)
+{
+	if (!starpu_profiling_status_get())
+		return;
+
+	struct starpu_profiling_task_info *profiling_info;
+	profiling_info = task->profiling_info;
+
+	if (profiling_info)
+	{
+		PAPI_stop(profiling_info->papi_event_set, profiling_info->papi_values);
+		for(int i=0; i<papi_nevents; i++)
+		{
+			_STARPU_TRACE_PAPI_TASK_EVENT(papi_events[i], task, profiling_info->papi_values[i]);
+		}
+		PAPI_cleanup_eventset(profiling_info->papi_event_set);
+		PAPI_destroy_eventset(&profiling_info->papi_event_set);
+	}
+}
+#endif
+
 void _starpu_profiling_start(void)
 {
 	const char *env;

+ 6 - 0
src/profiling/profiling.h

@@ -66,6 +66,12 @@ void _starpu_bus_update_profiling_info(int src_node, int dst_node, size_t size);
 void _starpu_profiling_set_task_push_start_time(struct starpu_task *task);
 void _starpu_profiling_set_task_push_end_time(struct starpu_task *task);
 
+#ifdef STARPU_PAPI
+/* Functions for papi task profilling */
+void _starpu_profiling_papi_task_start_counters(struct starpu_task *task);
+void _starpu_profiling_papi_task_stop_counters(struct starpu_task *task);
+#endif
+
 /* This function needs to be called before other starpu_profile_* functions */
 void _starpu_profiling_init(void);