-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
topdown: Created a component for interfacing with Intel's PERF_METRIC…
…S MSR Add a component that collects Intel's topdown metrics from the PERF_METRICS MSR and automatically converts the raw metric values to user-consumable percentages. The intent of this component is to provide an intuitive interface for accessing topdown metrics on the supported processors. Tested on a RaptorLake-S/HX machine (family/model/stepping 0x6/0xb7/0x1). To add other supported architectures the switch statment in _topdown_init_component() should be populated for the architecture's model number, whether it supports level 2 topdown metrics, and in the case of a heterogeneous processor what core type it must be run on.
- Loading branch information
Showing
8 changed files
with
1,420 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# TOPDOWN Component | ||
|
||
The `topdown` component enables accessing the `PERF_METRICS` Model Specific | ||
Register (MSR) of modern Intel PMUs, and makes it simple to properly | ||
interpret the results. | ||
|
||
* [Enabling the TOPDOWN Component](#enabling-the-topdown-component) | ||
* [Adding More Architectures](#adding_more_architectures) | ||
|
||
## Enabling the TOPDOWN Component | ||
|
||
To enable reading of topdown metrics the user needs to link against a | ||
PAPI library that was configured with the topdown component enabled. As an | ||
example the following command: `./configure --with-components="topdown"` is | ||
sufficient to enable the component. | ||
|
||
## Interpreting Results | ||
|
||
The events added by this component ending in "_PERC" should be cast to double | ||
values in order to be properly interpreted as percentages. An example of how | ||
to do so follows: | ||
|
||
PAPI_start(EventSet); | ||
|
||
/* some block of code... */ | ||
|
||
PAPI_stop(EventSet, values); | ||
|
||
printf("First metric was %.1f\n", *((double *)(&values[0]))); | ||
|
||
## Adding More Architectures | ||
|
||
To contribute more supported architectures to the component, add the cpuid model | ||
of the architecture to the case statement in `_topdown_init_component` of | ||
[topdown.c](./topdown.c) and set the relevant options (`supports_l2`, etc.) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
COMPSRCS += components/topdown/topdown.c | ||
COMPOBJS += topdown.o | ||
|
||
topdown.o: components/topdown/topdown.c components/topdown/topdown.h $(HEADERS) | ||
$(CC) $(LIBCFLAGS) $(OPTFLAGS) -c components/topdown/topdown.c -o topdown.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
NAME=topdown | ||
include ../../Makefile_comp_tests.target | ||
|
||
%.o:%.c | ||
$(CC) $(CFLAGS) $(OPTFLAGS) $(INCLUDE) -c -o $@ $< | ||
|
||
TESTS = topdown_basic topdown_L1 topdown_L2 | ||
|
||
topdown_tests: $(TESTS) | ||
|
||
topdown_basic: topdown_basic.o $(UTILOBJS) $(PAPILIB) | ||
$(CC) $(CFLAGS) $(INCLUDE) -o topdown_basic topdown_basic.o $(UTILOBJS) $(PAPILIB) $(LDFLAGS) | ||
|
||
topdown_L1: topdown_L1.o $(UTILOBJS) $(PAPILIB) | ||
$(CC) $(CFLAGS) $(INCLUDE) -o topdown_L1 topdown_L1.o $(UTILOBJS) $(PAPILIB) $(LDFLAGS) | ||
|
||
topdown_L2: topdown_L2.o $(UTILOBJS) $(PAPILIB) | ||
$(CC) $(CFLAGS) $(INCLUDE) -o topdown_L2 topdown_L2.o $(UTILOBJS) $(PAPILIB) $(LDFLAGS) | ||
|
||
|
||
clean: | ||
rm -f $(TESTS) *.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Specifically tests that the Level 1 topdown events make sense. | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <string.h> | ||
|
||
#include "papi.h" | ||
#include "papi_test.h" | ||
|
||
#define NUM_EVENTS 4 | ||
#define PERC_TOLERANCE 1.5 | ||
|
||
// fibonacci function to serve as a benchable code section | ||
void __attribute__((optimize("O0"))) fib(int n) | ||
{ | ||
long i, a = 0; | ||
int b = 1; | ||
for (i = 0; i < n; i++) | ||
{ | ||
b = b + a; | ||
a = b - a; | ||
} | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int i, quiet, retval; | ||
int EventSet = PAPI_NULL; | ||
const PAPI_component_info_t *cmpinfo = NULL; | ||
int numcmp, cid, topdown_cid = -1; | ||
long long values[NUM_EVENTS]; | ||
double tmp; | ||
|
||
/* Set TESTS_QUIET variable */ | ||
quiet = tests_quiet(argc, argv); | ||
|
||
/* PAPI Initialization */ | ||
retval = PAPI_library_init(PAPI_VER_CURRENT); | ||
if (retval != PAPI_VER_CURRENT) | ||
{ | ||
test_fail(__FILE__, __LINE__, "PAPI_library_init failed\n", retval); | ||
} | ||
|
||
if (!quiet) | ||
{ | ||
printf("Testing topdown component with PAPI %d.%d.%d\n", | ||
PAPI_VERSION_MAJOR(PAPI_VERSION), | ||
PAPI_VERSION_MINOR(PAPI_VERSION), | ||
PAPI_VERSION_REVISION(PAPI_VERSION)); | ||
} | ||
|
||
/*******************************/ | ||
/* Find the topdown component */ | ||
/*******************************/ | ||
numcmp = PAPI_num_components(); | ||
for (cid = 0; cid < numcmp; cid++) | ||
{ | ||
if ((cmpinfo = PAPI_get_component_info(cid)) == NULL) | ||
{ | ||
test_fail(__FILE__, __LINE__, "PAPI_get_component_info failed\n", 0); | ||
} | ||
if (!quiet) | ||
{ | ||
printf("\tComponent %d - %d events - %s\n", cid, | ||
cmpinfo->num_native_events, | ||
cmpinfo->name); | ||
} | ||
if (strstr(cmpinfo->name, "topdown")) | ||
{ | ||
topdown_cid = cid; | ||
|
||
/* check that the component is enabled */ | ||
if (cmpinfo->disabled) | ||
{ | ||
printf("Topdown component is disabled: %s\n", cmpinfo->disabled_reason); | ||
test_fail(__FILE__, __LINE__, "Component is not enabled\n", 0); | ||
} | ||
} | ||
} | ||
|
||
if (topdown_cid < 0) | ||
{ | ||
test_skip(__FILE__, __LINE__, "Topdown component not found\n", 0); | ||
} | ||
|
||
if (!quiet) | ||
{ | ||
printf("\nFound Topdown Component at id %d\n", topdown_cid); | ||
printf("\nAdding the level 1 topdown metrics..\n"); | ||
} | ||
|
||
/* Create EventSet */ | ||
retval = PAPI_create_eventset(&EventSet); | ||
if (retval != PAPI_OK) | ||
{ | ||
test_fail(__FILE__, __LINE__, | ||
"PAPI_create_eventset()", retval); | ||
} | ||
|
||
/* Add the level 1 topdown metrics */ | ||
retval = PAPI_add_named_event(EventSet, "TOPDOWN_RETIRING_PERC"); | ||
if (retval != PAPI_OK) | ||
{ | ||
test_fail(__FILE__, __LINE__, | ||
"Error adding TOPDOWN_RETIRING_PERC", retval); | ||
} | ||
retval = PAPI_add_named_event(EventSet, "TOPDOWN_BAD_SPEC_PERC"); | ||
if (retval != PAPI_OK) | ||
{ | ||
test_fail(__FILE__, __LINE__, | ||
"Error adding TOPDOWN_BAD_SPEC_PERC", retval); | ||
} | ||
retval = PAPI_add_named_event(EventSet, "TOPDOWN_FE_BOUND_PERC"); | ||
if (retval != PAPI_OK) | ||
{ | ||
test_fail(__FILE__, __LINE__, | ||
"Error adding TOPDOWN_FE_BOUND_PERC", retval); | ||
} | ||
retval = PAPI_add_named_event(EventSet, "TOPDOWN_BE_BOUND_PERC"); | ||
if (retval != PAPI_OK) | ||
{ | ||
test_fail(__FILE__, __LINE__, | ||
"Error adding TOPDOWN_BE_BOUND_PERC", retval); | ||
} | ||
|
||
/* stat a loop-based calculation of the sum of the fibonacci sequence */ | ||
/* the workload needs to be fairly large in order to acquire an accurate */ | ||
/* set of measurements */ | ||
PAPI_start(EventSet); | ||
fib(6000000); | ||
PAPI_stop(EventSet, values); | ||
|
||
/* run some sanity checks: */ | ||
|
||
/* first, the sum of all level 1 metric percentages should be 100% */ | ||
tmp = 0; | ||
for (i=0; i<NUM_EVENTS; i++) { | ||
tmp += *((double *)(&values[i])); | ||
} | ||
if (!quiet) | ||
printf("L1 metric percentages sum to %.2f%%\n", tmp); | ||
if (tmp < 100 - PERC_TOLERANCE || tmp > 100 + PERC_TOLERANCE) { | ||
test_fail(__FILE__, __LINE__, | ||
"Level 1 topdown metric percentages did not sum to 100%%\n", 1); | ||
} | ||
|
||
if (!quiet) | ||
printf("\tRetiring:\t%.1f%%\n", *((double *)(&values[0]))); | ||
|
||
/* next, verify that the percentage of bad spec slots is reasonable. */ | ||
/* for this benchmark, we can expect very low rate of bad speculation */ | ||
/* due to the fact that it consists of a simple for loop */ | ||
if (!quiet) | ||
printf("\tBad spec:\t%.1f%%\n", *((double *)(&values[1]))); | ||
if (*((double *)(&values[1])) > 5.0) { | ||
test_warn(__FILE__, __LINE__, | ||
"The percentage of slots affected by bad speculation was unexpectedly high", 1); | ||
} | ||
|
||
/* finally, make sure the frontend/backend bound percentages make sense */ | ||
/* we should expect this benchmark to be significantly more limited */ | ||
/* by the back end, so check that be bound is larger than the fe bound */ | ||
if (!quiet) { | ||
printf("\tFrontend bound:\t%.1f%%\n", *((double *)(&values[2]))); | ||
printf("\tBackend bound:\t%.1f%%\n", *((double *)(&values[3]))); | ||
|
||
} | ||
if (*((double *)(&values[2])) > *((double *)(&values[3]))) { | ||
test_warn(__FILE__, __LINE__, | ||
"Frontend bound should be significantly smaller than backend bound", 1); | ||
} | ||
|
||
return 0; | ||
} |
Oops, something went wrong.