Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
This example introduces
   hardware cycle and event counters, user interface
   pmc_data_t       -- raw data collected by pmc_read()
   pmc_cycle()      -- access functions for pmc_data_t

Previous example       -- exclusive access
Download this example
Next example           -- pmc_counter_t, intro
Return to Main Menu

Compile with gcc -o menu5 -O `pmc_options` menu5.c -lpmc Try these examples: menu5 menu5 -p menu5 -g 0
#include <pmc_lib.h> int main(int argc, char * argv[]) { pmc_control_t Ctl = pmc_control_null; pmc_data_t t0, t1; if (pmc_getargs(stderr, argv[0], &argc, &argv, &Ctl) == FALSE) { exit(1); } printf("pmc_event_counters = %d\n", pmc_event_counters); printf("sizeof(pmc_data_t) = %d\n", sizeof(pmc_data_t)); printf("sizeof(pmc_cycle_t) = %d\n", sizeof(pmc_cycle_t)); printf("sizeof(pmc_event_t) = %d\n", sizeof(pmc_event_t)); printf("pmc_cycle_bits = %d\n", pmc_cycle_bits); printf("pmc_event_bits = %d\n", pmc_event_bits); if (pmc_open(0) == FALSE) /* open /dev/pmc */ { exit(1); } pmc_read(&t0); /* read the counters */ /* do something */ pmc_read(&t1); /* read the counters */ pmc_close(); /* close /dev/pmc */ printf("t0.pmc_cycle() = %016llx\n", pmc_cycle(&t0)); printf("t0.pmc_event(0) = %016llx\n", pmc_event(&t0,0)); printf("t0.pmc_event(1) = %016llx\n", pmc_event(&t0,1)); printf("t1.pmc_cycle() = %016llx\n", pmc_cycle(&t1)); printf("t1.pmc_event(0) = %016llx\n", pmc_event(&t1,0)); printf("t1.pmc_event(1) = %016llx\n", pmc_event(&t1,1)); printf("t0.pmc_second() = %16.9f\n", pmc_second(pmc_cycle(&t0))); printf("t1.pmc_second() = %16.9f\n", pmc_second(pmc_cycle(&t1))); exit(0); }
Synopsis typedef struct { ... } pmc_data_t; typedef unsigned long long int pmc_cycle_t; typedef unsigned long long int pmc_event_t; #define pmc_cycle_bits 64 /* Intel or AMD */ #define pmc_event_bits 40 /* 40 with Intel, 48 with AMD Athlon */ pmc_cycle_t pmc_cycle(const pmc_data_t * const a); pmc_event_t pmc_event(const pmc_data_t * const a, const int i); double pmc_second(const pmc_cycle_t c); extern double pmc_seconds_per_cycle;
Naming convention These values represent a moment in time, so cycle and event are singular.
The pmc_data_t type holds a consistent set of raw cycle and event counter values obtained by pmc_read(). The components are opaque, and are translated to pmc_cycle_t and pmc_event_t by pmc_cycle() and pmc_event(), respectively. The effective numbers of bits in the counters are given by pmc_cycle_bits and pmc_event_bits, and the types pmc_cycle_t and pmc_event_t will have at least this many bits. There is no need to access the components of pmc_data_t directly; depending on the processor, some of the bits may need to be filtered out by pmc_event(). The typedef also contains an alignment request, which the compiler respects as a global or static local, but not as an automatic local on the runtime stack. In the current implementation, pmc_data_t is padded to 32 bytes, and aligned to a 32 byte boundary, so the data ideally exactly fills one cache line; on the AMD Athlon, the padding is to 64 bytes. Conversion from processor cycles to seconds via pmc_second() uses the MHz rating supplied to pmc_getargs() by the -mhz option. If you did not use pmc_getargs() to read from the command line, you should assign the appropriate value to the global variable pmc_seconds_per_cycle, or you can accept the value given by the installation. Unless the cycle counter has been reset, it contains the number of processor cycles since system startup. The event counters are often reset, and can overflow in relatively short time periods if counting a frequent event. The particular counter values are usually not relevant; use pmc_accumulate() to compute the number of cycles and events associated with a time interval.
Forward References pmc_read() pmc_accumulate()

Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
Author: Don Heller,
Last revised: 2 August 2000