diff options
author | mrchebas@gmail.com <unknown> | 2006-11-09 07:57:46 +0000 |
---|---|---|
committer | mrchebas@gmail.com <unknown> | 2006-11-09 07:57:46 +0000 |
commit | 2b522adea22f77a1c03230f5c9865c00bedb5a5b (patch) | |
tree | 080f40d42babe0435563f37f35e494ba65e0fdd6 /rts | |
parent | fe07f054d7ae5e10b14d5fed730fe4424dabd587 (diff) | |
download | haskell-2b522adea22f77a1c03230f5c9865c00bedb5a5b.tar.gz |
Selection of PAPI events via RTS command line
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Papi.c | 90 | ||||
-rw-r--r-- | rts/RtsFlags.c | 35 |
2 files changed, 92 insertions, 33 deletions
diff --git a/rts/Papi.c b/rts/Papi.c index 8ce3cc2381..5b4f7852db 100644 --- a/rts/Papi.c +++ b/rts/Papi.c @@ -1,9 +1,10 @@ - +#ifdef USE_PAPI /* ugly */ #include "Papi.h" #include "Rts.h" #include "RtsUtils.h" #include "Stats.h" +#include "RtsFlags.h" /* These constants specify which events to keep track of. @@ -23,7 +24,13 @@ struct _papi_events { char * event_name; }; -#define PAPI_ADD_EVENT(EVENT) { EVENT, #EVENT } +#define PAPI_ADD_EVENT(EVENT) \ + { \ + ASSERT(n_papi_events<MAX_PAPI_EVENTS); \ + papi_events[n_papi_events].event_code = EVENT; \ + papi_events[n_papi_events].event_name = #EVENT; \ + n_papi_events++; \ + } /* Beware, these counters are Opteron specific */ #define FR_BR 0x40000040 @@ -47,7 +54,7 @@ struct _papi_events { papi_counter(EVENTSET,EVENT)*100.0/papi_counter(EVENTSET,EVENTTOT)) /* Number of counted events, computed from size of papi_events */ -#define N_PAPI_EVENTS ((int)(sizeof(papi_events)/sizeof(struct _papi_events))) +#define N_PAPI_EVENTS n_papi_events /* This is bad, it should be in a header */ #define BIG_STRING_LEN 512 @@ -62,6 +69,10 @@ int GCEvents = PAPI_NULL; int papi_error; +/* Arbitrary, to avoid using malloc */ +#define MAX_PAPI_EVENTS 10 + +int n_papi_events = 0; /* If you want to add events to count, extend the * papi_events array and the papi_report function. @@ -69,30 +80,34 @@ int papi_error; /* Events counted during GC and Mutator execution */ /* There's a trailing comma, do all C compilers accept that? */ -static struct _papi_events papi_events[] = { - PAPI_ADD_EVENT(PAPI_TOT_CYC), -#if PAPI_COUNT_BRANCHES - PAPI_ADD_EVENT(FR_BR), - PAPI_ADD_EVENT(FR_BR_MIS), - /* Docs are wrong? Opteron does not count indirect branch misses apparently */ - PAPI_ADD_EVENT(FR_BR_MISCOMPARE), -#endif -#if PAPI_COUNT_STALLS - PAPI_ADD_EVENT(FR_DISPATCH_STALLS_BR), - PAPI_ADD_EVENT(FR_DISPATCH_STALLS_FULL_LS), -#endif -#if PAPI_COUNT_DCACHE1_MISSES - PAPI_ADD_EVENT(PAPI_L1_DCA), - PAPI_ADD_EVENT(PAPI_L1_DCM), -#endif -#if PAPI_COUNT_DCACHE2_MISSES - PAPI_ADD_EVENT(PAPI_L2_DCA), - PAPI_ADD_EVENT(PAPI_L2_DCM), -#endif +static struct _papi_events papi_events[MAX_PAPI_EVENTS]; + +static void +init_countable_events(void) +{ + PAPI_ADD_EVENT(PAPI_TOT_CYC); + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_BRANCH) { + PAPI_ADD_EVENT(FR_BR); + PAPI_ADD_EVENT(FR_BR_MIS); + /* Docs are wrong? Opteron does not count indirect branch misses exclusively */ + PAPI_ADD_EVENT(FR_BR_MISCOMPARE); + } + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_STALLS) { + PAPI_ADD_EVENT(FR_DISPATCH_STALLS_BR); + PAPI_ADD_EVENT(FR_DISPATCH_STALLS_FULL_LS); + } + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L1) { + PAPI_ADD_EVENT(PAPI_L1_DCA); + PAPI_ADD_EVENT(PAPI_L1_DCM); + } + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L2) { + PAPI_ADD_EVENT(PAPI_L2_DCA); + PAPI_ADD_EVENT(PAPI_L2_DCM); + } }; -long_long MutatorCounters[N_PAPI_EVENTS]; -long_long GCCounters[N_PAPI_EVENTS]; +long_long MutatorCounters[MAX_PAPI_EVENTS]; +long_long GCCounters[MAX_PAPI_EVENTS]; /* Extract the value corresponding to an event */ @@ -118,28 +133,32 @@ papi_report(long_long PapiCounters[]) /* I need to improve formatting aesthetics */ PAPI_REPORT(PapiCounters,PAPI_TOT_CYC); -#if PAPI_COUNT_BRANCHES + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_BRANCH) { PAPI_REPORT(PapiCounters,FR_BR); PAPI_REPORT(PapiCounters,FR_BR_MIS); PAPI_REPORT_PCT(PapiCounters,FR_BR_MIS,FR_BR); PAPI_REPORT_PCT(PapiCounters,FR_BR_MISCOMPARE,FR_BR); -#endif -#if PAPI_COUNT_STALLS + } + + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_STALLS) { PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_BR); PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_BR,PAPI_TOT_CYC); PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS); PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS,PAPI_TOT_CYC); -#endif -#if PAPI_COUNT_DCACHE1_MISSES + } + + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L1) { PAPI_REPORT(PapiCounters,PAPI_L1_DCA); PAPI_REPORT(PapiCounters,PAPI_L1_DCM); PAPI_REPORT_PCT(PapiCounters,PAPI_L1_DCM,PAPI_L1_DCA); -#endif -#if PAPI_COUNT_DCACHE2_MISSES + } + + if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L2) { PAPI_REPORT(PapiCounters,PAPI_L2_DCA); PAPI_REPORT(PapiCounters,PAPI_L2_DCM); PAPI_REPORT_PCT(PapiCounters,PAPI_L2_DCM,PAPI_L2_DCA); -#endif + } + } /* Add the events of papi_events into an event set */ @@ -160,6 +179,8 @@ void papi_init_eventsets(void) { + init_countable_events(); + /* One event set for the mutator and another for the GC */ PAPI_CHECK( PAPI_create_eventset(&MutatorEvents)); PAPI_CHECK( PAPI_create_eventset(&GCEvents)); @@ -195,3 +216,6 @@ papi_stop_gc_count(void) PAPI_CHECK( PAPI_accum(GCEvents,GCCounters)); PAPI_CHECK( PAPI_stop(GCEvents,NULL)); } + + +#endif /* USE_PAPI */ diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c index 7b8a4d1d68..b2bb9e79c0 100644 --- a/rts/RtsFlags.c +++ b/rts/RtsFlags.c @@ -301,6 +301,10 @@ void initRtsFlagsDefaults(void) RtsFlags.TraceFlags.timestamp = rtsFalse; RtsFlags.TraceFlags.sched = rtsFalse; + +#ifdef USE_PAPI + RtsFlags.PapiFlags.eventType = PAPI_FLAG_BRANCH; +#endif } static const char * @@ -449,6 +453,16 @@ usage_text[] = { #if defined(GRAN) /* ToDo: fill in decent Docu here */ " -b... All GranSim options start with -b; see GranSim User's Guide for details", #endif +#if defined(USE_PAPI) +" -aX Perform measurements using PAPI, it should be used with the -s<file> option.", +" Where X is one of:", +"", +/* " y - cycles", */ +" 1 - level 1 cache misses", +" 2 - level 2 cache misses", +" b - branch mispredictions", +" s - stalled cycles", +#endif "", "RTS options may also be specified using the GHCRTS environment variable.", "", @@ -647,6 +661,27 @@ error = rtsTrue; } break; +#ifdef USE_PAPI + case 'a': + switch(rts_argv[arg][2]) { + case '1': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_CACHE_L1; + break; + case '2': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_CACHE_L2; + break; + case 'b': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_BRANCH; + break; + case 's': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_STALLS; + break; + default: + bad_option( rts_argv[arg] ); + } + break; +#endif + case 'B': RtsFlags.GcFlags.ringBell = rtsTrue; break; |