Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
This example introduces
pmc_events.h -- symbolic names of event codes
pmc_event_set_t -- events for concurrent measurement
pmc_event_label_t -- textual description of an event set
pmc_event_counters -- number of event counters in a set
pmc_event_valid()
pmc_event_name()
pmc_event_description()
Previous example -- pmc_getargs()
Download this example
Next example -- Pentium Pro/II/III events
Return to Main Menu
For a Pentium Pro/II/III, compile with
gcc -o menu3 -O `pmc_options` menu3.c -lpmc
Try these examples:
menu3
rabbit -l | tr a-z A-Z
#include <pmc_lib.h>
int main(int argc, char * argv[])
{
int i, j;
pmc_control_t Ctl = pmc_control_null;
pmc_event_set_t Event[3] = { /* initialize event sets */
{DATA_MEM_REFS, BUS_TRAN_MEM}, /* symbols defined in pmc_events.a */
{INST_RETIRED, UOPS_RETIRED},
{MUL, DIV}
};
pmc_event_label_t Label[3] = { /* initialize event set labels */
"Fraction of memory references that cause bus transactions",
"Micro-operations per instruction",
"Floating-point operations"
};
/* required, to initialize internal event tables */
if (pmc_getargs(stderr, argv[0], NULL, NULL, &Ctl) == FALSE)
{ exit(1); }
Event[0][0] = DATA_MEM_REFS; /* assign event sets */
Event[0][1] = BUS_TRAN_MEM;
Event[1][0] = INST_RETIRED;
Event[1][1] = UOPS_RETIRED;
Event[2][0] = MUL;
Event[2][1] = DIV;
/* pmc_control_t components used by pmc_counter_init() */
Ctl.event[0] = Event[0][0];
Ctl.event[1] = Event[0][1];
#if 0
Ctl.event = Event[0]; /* gcc: "incompatible types in assignment" */
#endif
/* pmc_control_t list of event sets used by pmc_print_results() */
Ctl.event_pairs = 3;
Ctl.events = Event;
Ctl.labels = Label;
for (i = 0; i < 3; i++) /* event set i */
for (j = 0; j < pmc_event_counters; j++) /* event j in set i */
{
int event = Event[i][j];
if (pmc_event_valid(event,j)) /* valid for counter j? */
{
printf("0x%2x %3d %s\n"
" %s\n",
event, event, pmc_event_name(event,j),
pmc_event_description(event,j)
);
}
else
{
printf("0x%2x %3d not valid for counter %d\n",
event, event, j);
}
}
exit(0);
}
Synopsis
#include <pmc_events.h>
#define pmc_event_counters 2 /* 2 with Intel; 4 with AMD Athlon */
typedef int pmc_event_set_t[pmc_event_counters];
typedef char pmc_event_label_t[PMC_STRING];
int pmc_event_valid(const int code, const int counter);
const char * pmc_event_name(const int code, const int counter);
const char * pmc_event_description(const int code, const int counter);
The processor allows pmc_event_counters events to be counted concurrently.
In the pmc_control_t data structure, each pmc_event_set_t has a corresponding
pmc_event_label_t used by pmc_print_results().
Each event that can be counted by the hardware has a processor-dependent
numeric code, that is most easily obtained from 'rabbit -c'. The symbolic
names of the events are given in pmc_events.h, which is included by pmc_lib.h.
The functions pmc_event_name() and pmc_event_description() return pointers
to the [mostly lower case] symbolic name and description strings.
Some events are only valid in one counter, such as the MUL and DIV events
above. This is indicated by the description, and checked by pmc_getargs().
If you are uncertain whether event code n is valid, try 'rabbit --e n -c'.
pmc_event_valid() returns FALSE if the event code is not valid for the
indicated counter.
The output for this example is
0x43 67 data_mem_refs
L1 d-cache, all memory references, both cacheable and non-cacheable
0x6f 111 bus_tran_mem
external bus, memory transactions (--bus_agent)
0xc0 192 inst_retired
instruction decode and retire unit, instructions retired
0xc2 194 uops_retired
instruction decode and retire unit, micro-operations retired
0x12 18 not valid for counter 0
0x13 19 div
floating-point unit, FP divides (counter 1 only)
Forward References
pmc_counter_init()
pmc_print_results()
Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
Author: Don Heller, dheller@scl.ameslab.gov
Last revised: 2 August 2000