PAPI Events - icl-utk-edu/papi GitHub Wiki


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 utils/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 <papi.h>
#include <stdio.h>
#include <stdlib.h>

void handle_error (int retval)
{
    printf("PAPI error %d: %s\n", retval, PAPI_strerror(retval));
    exit(1);
}
	
int 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)
        handle_error(retval);
	
    /* 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);
	
    /* Executes if all low-level PAPI
    function calls returned PAPI_OK */
    printf("\033[0;32mPASSED\n\033[0m");
    exit(0); 
}

Output

PASSED

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

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 utils/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 EventCode;
int retval = PAPI_query_event(EventCode);

Arguments for PAPI_query_event:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
int EventCode;
PAPI_event_info_t info;
int retval = PAPI_get_event_info(EventCode, &info);

Arguments for PAPI_get_event_info:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • info -- structure with event information.
int EventCode, modifier;
int retval = PAPI_enum_event(&EventCode, modifier);

Arguments for PAPI_enum_event:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • modifier -- modifies the search criteria; for preset events, returns all events or only available events; for native events, the definition is platform dependent.

Fortran:

use iso_c_binding
integer(c_int) EventCode, check
call PAPIF_query_event(EventCode, check)

Fortran arguments for PAPIF_query_event:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • check -- an error return value for Fortran.
    use iso_c_binding
    integer(c_int) EventCode, count, flags, check
    character(PAPI_MAX_STR_LEN, c_char) symbol, long_descr,
& short_descr, event_note
    call PAPIF_get_event_info(EventCode, symbol, long_descr,
& short_descr, count, event_note, flags, check)

Fortran arguments for PAPIF_get_event_info:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • symbol -- the event symbol, or name, such as the preset name, PAPI_BR_CN.
  • long_descr -- a descriptive string for the event of length less than PAPI_MAX_STR_LEN.
  • short_descr -- a short descriptive string for the event of length less than 18 characters.
  • count -- zero if the event CANNOT be counted.
  • event_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.
  • check -- an error return value for Fortran.
use iso_c_binding
integer(c_int) EventCode, modifier, check
call PAPIF_enum_event(EventCode, modifier, check)

Fortran arguments for PAPIF_enum_event:

  • EventCode -- a defined event, such as PAPI_TOT_INS.
  • modifier -- modifies the search criteria; for preset events, returns all events or only available events; for native events, the definition is platform dependent.
  • check -- an error return value for Fortran.

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 utils/papi_avail.c or utils/papi_native_avail.c for details.

Example

#include <papi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
        
void handle_error (int retval)
{
    printf("PAPI error %d: %s\n", retval, PAPI_strerror(retval));
    exit(1);
}
	
int 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)
        handle_error(retval);
	    
    /* Check to see if the preset, PAPI_TOT_INS, exists */
    retval = PAPI_query_event(PAPI_TOT_INS);
    if (retval != PAPI_OK)
        handle_error(retval);
	    
    /* Get details about the preset, PAPI_TOT_INS */
    retval = PAPI_get_event_info( PAPI_TOT_INS, &info );
    if (retval != PAPI_OK)
        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 );

    /* Executes if all low-level PAPI
    function calls returned PAPI_OK */
    printf("\033[0;32m\n\nPASSED\n\033[0m");
    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.


PASSED

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 PAPI functions return PAPI_OK and the possible above output is returned. 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:

const char *EventName;
int EventCode;
int retval = PAPI_event_name_to_code(EventName, &EventCode);

Arguments for PAPI_event_name_to_code:

  • EventName -- a string containing the event name as listed in PAPI_presets or discussed in PAPI_native.
  • EventCode -- stores the numeric code for the event.
int EventCode;
char EventName[PAPI_MAX_STR_LEN];
int retval = PAPI_event_code_to_name(EventCode, EventName);

Arguments for PAPI_event_code_to_name:

  • EventCode -- the numeric code for the event.
  • EventName -- stores a string containing the event name as listed in PAPI_presets or discussed in PAPI_native.

Fortran:

use iso_c_binding
character(PAPI_MAX_STR_LEN, c_char) EventName
integer(c_int) EventCode, check
call PAPIF_event_name_to_code(EventName, EventCode, check)

Fortran arguments for PAPIF_event_name_to_code:

  • EventName -- a string containing the event name as listed in PAPI_presets or discussed in PAPI_native.
  • EventCode -- the numeric code for the event.
  • check -- an error return value for Fortran.
use iso_c_binding
integer(c_int) EventCode, check
character(PAPI_MAX_STR_LEN, c_char) EventName
call PAPIF_event_code_to_name(EventCode, EventName, check)

Fortran arguments for PAPIF_event_code_to_name:

  • EventCode -- the numeric code for the event.
  • EventName -- a string containing the event name as listed in PAPI_presets or discussed in PAPI_native.
  • check -- an error return value for Fortran.

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>
#include <stdlib.h>

void handle_error (int retval)
{
   printf("PAPI error %d: %s\n", retval, PAPI_strerror(retval));
   exit(1);
}

int 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)
       handle_error(retval);      
   	
   EventCode = 0 | PAPI_NATIVE_MASK;
   do {
       /* Translate the integer code to a string */
       retval = PAPI_event_code_to_name(EventCode, EventCodeStr);
       /* Print all the native events for this platform if PAPI_OK*/
       if (retval == PAPI_OK)
           printf("Name: %s\nCode: %x\n", EventCodeStr, EventCode);
   	
   } while (PAPI_enum_event(&EventCode, 0) == PAPI_OK);

   /* Executes if all low-level PAPI
   function calls returned PAPI_OK */
   printf("\033[0;32m\n\nPASSED\n\033[0m");
   exit(0);    
}

Possible 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


PASSED

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

On success, all PAPI functions return PAPI_OK and the above possible output is returned. On error, a non-zero error code is returned.

⚠️ **GitHub.com Fallback** ⚠️