Wiki

Clone wiki

papi / PAPI-Events


Events

Events are occurrences of specific signals related to the function of a processor or other subsystem. Hardware performance counters exist as a small set of registers that count events, such as cache misses and floating point operations while the program executes on the processor. Monitoring these events facilitates correlation between the structure of source/object code and the efficiency of the mapping of that code to the underlying architecture. Each processor has a number of events that are native to that architecture. PAPI provides a software abstraction of these architecture-dependent native events into a collection of preset events that are accessible through the PAPI interface.

Native Events

Native events comprise the set of all events that are available on the CPU. There are generally far more native events available than can be mapped onto PAPI preset events. Even if no preset event is available that exposes a given native event, native events can still be accessed directly. To use native events effectively you should be very familiar with the particular platform in use. PAPI provides access to native events on all supported platforms through the low-level interface. Native events use the same interface as used when setting up a preset event, but since a PAPI preset event definition is not available for native events, a native event name must often be translated into an event code before it can be used.

Native event codes and names are platform dependent, so native codes for one platform are not likely to work for any other platform. To determine the native events for your platform, see the native event lists for the various platforms in the processor architecture manual. On many platforms the meaning of a native event can be modified by a collection of unit masks, or modifiers. These modifiers are typically appended to the end of a base event name with a colon character. More than one modifier can be specified, but in many cases a base event with no modifiers cannot be counted. In such cases PAPI_add_event will fail, even though PAPI_query_event and PAPI_event_info succeed. Every attempt is made to keep native event names used by PAPI as similar as possible to those used in the vendor documentation. This is not always possible. The utility code util/papi_native_avail provides insight into the names of the native events for a specific platform.

Native events are specified as arguments to the low-level function, PAPI_add_event in a manner similar to adding PAPI preset events. In the following code example, a native event name is converted to an event code and added to an eventset by using PAPI_add_event:

#include <stdlib.h>
#include <stdio.h>
#include <papi.h>

main()
{
    int retval, EventSet = PAPI_NULL;
    unsigned int native = 0x0;
    PAPI_event_info_t info;

    /* Initialize the library */
    retval = PAPI_library_init(PAPI_VER_CURRENT);
    if (retval != PAPI_VER_CURRENT) {
        printf("PAPI library init error!\n");
        exit(1);
    }

    /* Create an EventSet */
    retval = PAPI_create_eventset(&EventSet);
    if (retval != PAPI_OK) handle_error(retval);

    /* Find the first available native event */
    native = PAPI_NATIVE_MASK | 0;
    retval = PAPI_enum_event(&native, PAPI_ENUM_FIRST);
    if (retval != PAPI_OK) handle_error(retval);

    /* Add it to the eventset */
    retval = PAPI_add_event(EventSet, native);
    if (retval != PAPI_OK) handle_error(retval);

    /* Exit successfully */
    printf("Success!\n");
    exit(0);
}

For more code examples using native events, see ctests/native.c and util/native_avail.c in the papi source distribution.

Preset Events

Preset events, also known as predefined events, are a common set of events deemed relevant and useful for application performance tuning. These events are typically found in many CPUs that provide performance counters and give access to the memory hierarchy, cache coherence protocol events, cycle and instruction counts, functional unit, and pipeline status. Furthermore, preset events are mappings from symbolic names (PAPI preset name) to machine specific definitions (native countable events) for a particular hardware resource. For example, Total Cycles (in user mode) is PAPI_TOT_CYC. Also, PAPI supports presets that may be derived from the underlying hardware metrics. For example, Total L1 Cache Misses (PAPI_L1_TCM) might be the sum of L1 Data Misses and L1 Instruction Misses on a given platform. A preset can be either directly available as a single counter, derived using a combination of counters, or unavailable on any particular platform.

The PAPI library names approximately 100 preset events, which are defined in the header file, papiStdEventDefs.h. For a given platform, a subset of these preset events can be counted through either a simple high-level programming interface or a more complete C or Fortran low-level interface. To determine exactly which preset events are available on a specific platform, run util/papi_avail.c in the papi source distribution.

The exact semantics of an event counter are platform dependent. PAPI preset names are mapped onto available events so as to map as many countable events as possible on different platforms. Due to hardware implementation differences, it is not necessarily feasible to directly compare the counts of a particular PAPI preset event obtained on different hardware platforms.

Event Query

The following low-level functions can be called to query about the existence of a preset or native event (in other words, if the hardware supports that certain event), and to get details about that event:

C:

int PAPI_query_event( int EventCode )
int PAPI_get_event_info( int EventCode, PAPI_event_info_t *info )
int PAPI_enum_event( int *EventCode, int modifier )

Fortran:

PAPIF_query_event( C_INT EventCode, C_INT check )
PAPIF_get_event_info( C_INT EventCode, C_STRING symbol, C_STRING long_descr, C_STRING short_descr, C_INT count, C_STRING event_note, C_INT flags, C_INT check )
PAPIF_enum_event( C_INT EventCode, C_INT modifier, C_INT check )

Arguments

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • symbol -- the event symbol, or name, such as the preset name, PAPI_BR_CN.
  • longDescr -- a descriptive string for the event of length less than PAPI_MAX_STR_LEN.
  • shortDescr -- a short descriptive string for the event of length less than 18 characters.
  • count -- zero if the event CANNOT be counted.
  • note -- additional text information about an event (if available).
  • flags -- provides additional information about an event, e.g., PAPI_DERIVED for an event derived from 2 or more other events.
  • modifier -- modifies the search criteria; for preset events, returns all events or only available events; for native events, the definition is platform dependent.

PAPI_query_event asks the PAPI library if the preset or native event exists on this architecture. If the event DOES exist, the function returns PAPI_OK. If the event DOES NOT exist, the function returns an error code.

PAPI_get_event_info asks the PAPI library for a copy of an event descriptor. This descriptor can then be used to investigate the details about the event. In Fortran, the individual fields in the descriptor are returned as parameters.

PAPI_enum_event asks the PAPI library to return an event code for the next sequential event based on the current event code and the modifier. This function can be used to enumerate all preset or native events on any platform. See util/papi_avail.c or util/papi_native_avail.c for details.

Example

#include <stdlib.h>
#include <stdio.h>
#include <papi.h>

main()
{
    int EventSet = PAPI_NULL;
    unsigned int native = 0x0;
    int retval, i;
    PAPI_event_info_t info;
    PAPI_event_info_t *infostructs;

    /* Initialize the library */
    retval = PAPI_library_init(PAPI_VER_CURRENT);

    if (retval != PAPI_VER_CURRENT) {
        fprintf(stderr,"PAPI library init error!\n");
        exit(1);
    }

    /* Check to see if the preset, PAPI_TOT_INS, exists */
    retval = PAPI_query_event( PAPI_TOT_INS );
    if (retval != PAPI_OK) {
        fprintf (stderr,"No instruction counter? How lame.\n");
        handle_error( retval );
    }

    /* Get details about the preset, PAPI_TOT_INS */
    retval = PAPI_get_event_info( PAPI_TOT_INS, &info );
    if ( retval != PAPI_OK ) {
        fprintf (stderr,"No event info? How lame.\n");
        handle_error( retval );
    }

    if ( info.count > 0 )
        printf ("This event is available on this hardware.\n");

    if ( strcmp( info.derived, "NOT_DERIVED" ))
        printf ( "This event is a derived event on this hardware.\n" );

    /* Count the number of available preset events between 
       PAPI_TOT_INS and the end of the preset list */
    retval = 0;
    i = PAPI_TOT_INS;

    while (PAPI_enum_event(&i, PAPI_ENUM_EVENTS) == PAPI_OK)
       retval++;
    printf ( "There are %d PRESET events after PAPI_TOT_INS.\n", retval );
    exit(0);
}

Output

If PAPI_TOT_INS is available on your system you will see something similar to the following:

This event is available on this hardware.
There are 56 PRESET events after PAPI_TOT_INS.

In the above code example, PAPI_query_event is used to see if a preset (PAPI_TOT_INS) exists, PAPI_get_event_info is used to query details about the event, and PAPI_enum_event is used to count the number of events in the preset list after this preset.

On success, all three of these functions return PAPI_OK, and on error, a non-zero error code is returned.

Event Translation

A preset or native event can be referenced by name or by event code. Most PAPI functions require an event code, while most user input and output is in terms of names. Two low-level functions are provided to translate between these formats:

C:

PAPI_event_name_to_code(EventName, EventCode)
PAPI_event_code_to_name(EventCode, EventName)

Fortran:

PAPIF_event_name_to_code(EventName, EventCode, check)
PAPIF_event_code_to_name(EventCode, EventName, check)

Arguments

  • EventCode -- a preset or native event of integer type, such as PAPI_TOT_INS.
  • EventName -- the event name string, such as the preset name, “PAPI_BR_CN”.

Note that the preset does not actually have to be available on a given platform to call these functions. Native event names are platform specific and where feasible match those given in the vendor documentation.

PAPI_event_name_to_code is used to translate an ASCII PAPI preset or native event name into an integer PAPI event code.

PAPI_event_code_to_name is used to translate an integer PAPI event code into an ASCII PAPI preset or native event name.

Using PAPI_event_code_to_name in conjunction with PAPI_enum_event is a good way to explore the names of native events on a specific platform, as shown in the following code example:

#include <papi.h>
#include <stdio.h>

main()
{
    int EventCode, retval;
    char EventCodeStr[PAPI_MAX_STR_LEN];

    /* Initialize the library */
    retval = PAPI_library_init(PAPI_VER_CURRENT);

    if  (retval != PAPI_VER_CURRENT) {
      fprintf(stderr, "PAPI library init error!\n");
      exit(1); 
     }

    EventCode = 0 | NATIVE_MASK;
    do {
       /* Translate the integer code to a string */
       if (PAPI_event_code_to_name(EventCode, EventCodeStr) == PAPI_OK)

          /* Print all the native events for this platform */
          printf("Name: %s\nCode: %x\n", EventCodeStr, EventCode);

    } while (PAPI_enum_event(&EventCode, 0) == PAPI_OK);
}

Output

Name: DATA_MEM_REFS
Code: 40000000
Name: DCU_LINES_IN
Code: 40000001
Name: DCU_M_LINES_IN
Code: 40000002
.
.
Name: SEG_REG_RENAMES_TOT
Code: 40000078
Name: RET_SEG_RENAMES
Code: 40000079

The output will vary depending on the platform. This was generated on an Intel Pentium III processor.

On success, all the functions return PAPI_OK and on error, a non-zero error code is returned.

Updated