Counter Interfaces
From PAPIDocs
Jump to: navigation, search

PAPI’S COUNTER INTERFACES

HIGH-LEVEL API

WHAT IS THE HIGH-LEVEL API?

The high-level API (Application Programming Interface) provides the ability to start, stop, and read the counters for a specified list of events. It is meant for programmers wanting simple event measurements using only PAPI preset events. Some of the benefits of using the high-level API rather than the low-level API are that it is easier to use and requires less setup (additional calls). This ease of use comes with somewhat higher overhead and loss of flexibility.

It should also be noted that the high-level API can be used in conjunction with the low-level API and in fact does call the low-level API. However, the high-level API by itself is only able to access those events countable simultaneously by the underlying hardware.

There are eight functions that represent the high-level API that allow the user to access and count specific hardware events. Note that these functions can be accessed from both C and Fortran. For a code example of using the high-level interface, see Simple Code Examples: High Level API or ctests/high-level.c in the PAPI source distribution.

For full details on the calling semantics of these functions, please refer to the PAPI Programmer’s Reference.


INITIALIZING THE HIGH-LEVEL API

The PAPI library is initialized implicitly by several high-level API calls. In addition to the three rate calls discussed later, either of the following two functions also implicitly initializes the library:

C:

 
PAPI_num_counters()
''PAPI_start_counters(*events, array_length)	''
 

Fortran:

 
PAPIF_num_counters(check)
PAPIF_start_counters''(*events'', ''array_length'', check)
 
ARGUMENTS
 
''*events'' -- an array of codes for events such as PAPI_INT_INS or a native event code.
''array_length'' -- the number of items in the ''events'' array.
 

PAPI_num_counters returns the optimal length of the values array for high-level functions. This value corresponds to the number of hardware counters supported by the current substrate. PAPI_num_counters initializes the PAPI library using PAPI_library_init if necessary.

PAPI_start_counters initializes the PAPI library (if necessary) and starts counting the events named in the events array. This function implicitly stops and initializes any counters running as a result of a previous call to PAPI_start_counters. It is the user’s responsibility to choose events that can be counted simultaneously by reading the vendor’s documentation. The size of array_length should be no larger than the value returned by PAPI_num_counters.

In the following code example, PAPI_num_counters is used to initialize the library and to get the number of hardware counters available on the system. Also, PAPI_start_counters is used to start counting events:

 
#include <papi.h>
 
main()
{
int Events[2] = { PAPI_TOT_CYC, PAPI_TOT_INS };
int num_hwcntrs = 0;

/* Initialize the PAPI library and get the number of counters available */
if ((num_hwcntrs = PAPI_num_counters()) <= PAPI_OK)  
    handle_error(1);

printf("This system has %d available counters.", num_hwcntrs);

if (num_hwcntrs > 2)
    num_hwcntrs = 2;

     /* Start counting events */
     if (PAPI_start_counters(Events, num_hwcntrs) != PAPI_OK)
         handle_error(1);
}
 
POSSIBLE OUTPUT (varies on different systems):
This system has 4 available counters.
 

On success, PAPI_num_counters returns the number of hardware counters available on the system and on error, a non-zero error code is returned.

'Optionally', the PAPI library can be initialized explicitly by using'PAPI_library_init'. This can be useful if you wish to call PAPI low-level API functions before using the high-level functions.

EXECUTION RATE CALLS

Three PAPI high-level functions are available to measure floating point or total instruction rates. These three calls are shown below:

C:

 
PAPI_flips(*''real_time, *proc_time, *flpins, *mflips'')
PAPI_flops(*''real_time, *proc_time, *flpins, *mflops'')
PAPI_ipc(*''real_time, *proc_time, *ins, *ipc'')

 

Fortran:

 
PAPIF_flips(''real_time, proc_time, flpins, mflips'', check)
PAPIF_flops(''real_time, proc_time, flpins, mflops'', check)
PAPIF_ipc(''real_time, proc_time, ins, ipc'', check)

 


ARGUMENTS
 
*real_time -- the total real (wallclock) time since the first rate call.
*proc_time -- the total process time since the first rate call.
*flpins    -- the total floating point instructions since the first rate call.
*mflips, *mflops
           -– Millions of floating point operations or instructions 
              per second achieved since the latest rate call.
*ins       -- the total instructions executed since the first PAPI_ipc call.
*ipc       -– instructions per cycle achieved since the latest PAPI_ipc call.
 

The first execution rate call initializes the PAPI library if needed, sets up the counters to monitor either PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS (depending on the call), and PAPI_TOT_CYC events, and starts the counters. Subsequent calls to the same rate function will read the counters and return total real time, total process time, total instructions or operations, and the appropriate rate of execution since the last call. A call to PAPI_stop_counters will reinitialize all values to 0. Sequential calls to different execution rate functions will return an error.

Note that on many platforms there may be subtle differences between floating point instructions and operations. Instructions are typically those execution elements most directly measured by the hardware counters. They may include floating point load and store instructions, and may count instructions such as FMA as one, even though two floating point operations have occurred. Consult the hardware documentation for your system for more details. Operations represent a derived value where an attempt is made, when possible, to more closely map to the theoretical definition of a floating point event.

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

For a code example, see ctest/flops.c or ctest/ipc.c in the papi source distribution.

READING, ACCUMULATING, AND STOPPING COUNTERS

Counters can be read, accumulated, and stopped by calling the following high-level functions, respectively:

C:

 
PAPI_read_counters(*''values, array_length'')
PAPI_accum_counters(*''values, array_length'')
PAPI_stop_counters(*''values, array_length'')

 

Fortran:

 
PAPIF_read_counters(''*''values, array_length'', ''check)
PAPIF_accum_counters(*''values'', ''array_length'', check)
PAPIF_stop_counters(*''values'', ''array_length'', check)

 


ARGUMENTS
 
''*values'' -- an array where to put the counter values. 
''array_length'' -- the number of items in the *values array. 

 

PAPI_read_counters, PAPI_accum_counters and PAPI_stop_counters all capture the values of the currently running counters into the array, values. Each of these functions behaves somewhat differently.

PAPI_read_counters copies the current counts into the elements of the values array, resets the counters to zero, and leaves the counters running.

PAPI_accum_counters adds the current counts into the elements of the values array and resets the counters to zero, leaving the counters running. Care should be exercised not to mix calls to PAPI_accum_counters with calls to the execution rate functions. Such intermixing is likely to produce unexpected results.

PAPI_stop_counters stops the counters and copies the current counts into the elements of the values array. This call can also be used to reset the rate functions if used with a NULL pointer to the values array.

In the following code example, PAPI_read_counters and PAPI_stop_counters are used to copy and stop event counters in an array, respectively:

 
#include <papi.h>

#define NUM_EVENTS 2

main()
{
int Events[NUM_EVENTS] = {PAPI_TOT_INS, PAPI_TOT_CYC};
long_long values[NUM_EVENTS];

/* Start counting events */
if (PAPI_start_counters(Events, NUM_EVENTS) != PAPI_OK)
   handle_error(1);

/* Do some computation here*/

/* Read the counters */
if (PAPI_read_counters(values, NUM_EVENTS) != PAPI_OK)
   handle_error(1);

/* Do some computation here */

/* Stop counting events */
if (PAPI_stop_counters(values, NUM_EVENTS) != PAPI_OK)
   handle_error(1);
}
 


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


LOW-LEVEL API

WHAT IS THE LOW-LEVEL API?

The low-level API (Application Programming Interface) manages hardware events in user-defined groups called Event Sets. It is meant for experienced application programmers and tool developers wanting fine-grained measurement and control of the PAPI interface. Unlike the high-level interface, it allows both PAPI preset and native events. Other features of the low-level API are the ability to obtain information about the executable and the hardware as well as to set options for multiplexing and overflow handling. Some of the benefits of using the low-level API rather than the high-level API are that it increases efficiency and functionality.

It should also be noted that the low-level interface could be used in conjunction with the high-level interface, as long as attention is paid to insure that the PAPI library is initialized prior to the first low-level PAPI call.

The low-level API is only as powerful as the substrate upon which it is built. Thus, some features may not be available on every platform. The converse may also be true, that more advanced features may be available on every platform and defined in the header file. Therefore, the user is encouraged to read the documentation for each platform carefully. There are approximately 50 functions that represent the low-level API. For a code example of using the low-level interface, see Simple Code Examples: Low-Level API or ctests/low_level.c in the PAPI source distribution.

Note that most functions are implemented in both C and Fortran, but some are implemented in only one of these two languages. For full details on the calling semantics of these functions, please refer to the PAPI Programmer’s Reference.


INITIALIZATION OF THE LOW-LEVEL API

The PAPI library must be initialized before it can be used. It can be initialized explicitly by calling the following low-level function:

C:

 
PAPI_library_init(''version'')

 

Fortran:

 
PAPIF_library_init(check)

 


ARGUMENT

version -- upon initialization, PAPI checks the argument against the internal value of PAPI_VER_CURRENT when the library was compiled. This guards against portability problems when updating the PAPI shared libraries on your system.

Note that this function must be called before calling any other low-level PAPI function.

On success, this function returns PAPI_VER_CURRENT.

On error, a positive return code other than PAPI_VER_CURRENT indicates a library version mismatch and a negative return code indicates an initialization error.

Beginning with PAPI 3.0, there are a number of options for examining the current version number of PAPI:

PAPI_VERSION produces an integer containing the complete current version including MAJOR, MINOR, and REVISION components. Typically the REVISION component changes with bug fixes or minor enhancements, the MINOR component changes with feature additions or API changes, and the MAJOR component changes with significant API structural changes.

PAPI_VER_CURRENT contains the MAJOR and MINOR components and is useful for determining library compatibility changes.

PAPI_VERSION_MAJOR,

PAPI_VERSION_MINOR,

PAPI_VERSION_REVISION are macros that extract specified component from the version number.

The following is a code example of using PAPI_library_init to initialize the PAPI library:

 
#include <papi.h>
#include <stdio.h>
int retval;

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

if (retval != PAPI_VER_CURRENT && retval > 0) {
  fprintf(stderr,"PAPI library version mismatch!\n");
  exit(1);
}

if (retval < 0) {
  fprintf(stderr, “Initialization error!\n”);
  exit(1);
}

fprintf(stdout, “PAPI Version Number\n”);
fprintf(stdout, “MAJOR:    %d\n”, PAPI_MAJOR(retval));
fprintf(stdout, “MINOR:    %d\n”, PAPI_MINOR(retval));
fprintf(stdout, “REVISION: %d\n”, PAPI_REVISION(retval));
}
 




OUTPUT FOR PAPI VERSION 3.5.0
 
PAPI Version Number
MAJOR:    3
MINOR:    5
REVISION: 0
 



EVENT SETS

WHAT ARE EVENT SETS?

Event Sets are user-defined groups of hardware events (preset or native), which are used in conjunction with one another to provide meaningful information. The user specifies the events to be added to an Event Set, and other attributes, such as: the counting domain (user or kernel), whether or not the events in the Event Set are to be multiplexed, and whether the Event Set is to be used for overflow or profiling. Other settings for the Event Set are maintained by PAPI, such as: what low-level hardware registers to use, the most recently read counter values, and the state of the Event Set (running/not running). Event Sets provide an effective abstraction for the organization of information associated with counting hardware events. The PAPI library manages the memory for Event Sets with a user interface through integer handles to simplify calling conventions. The user is free to allocate and use any number of them provided the substrate can provide the required resources. Only one Event Set can be in active use at any time in a given thread or process.


CREATING AN EVENT SET

An event set can be created by calling the following the low-level function:

C:

 
PAPI_create_eventset (''*EventSet'')

 

Fortran:

 
PAPIF_create_eventset(''EventSet, ''check)

 


ARGUMENT

EventSet -- Address of an integer location to store the new EventSet handle.

Once it has been created, the user may add hardware events to the EventSet by calling PAPI_add_event or PAPI_add_events.

On success, this function returns PAPI_OK. On error, a non-zero error code is returned.

For a code example using this function, see the next section.


ADDING EVENTS TO AN EVENT SET

Hardware events can be added to an event set by calling the following the low-level functions:

C:

 
PAPI_add_event(''EventSet, EventCode'')
PAPI_add_events(''EventSet, *EventCode, number'')

 

Fortran:

 
PAPIF_add_event(''EventSet, EventCode, ''check)
PAPIF_add_events(''EventSet, EventCode, number, ''check)

 


ARGUMENTS
 
''EventSet'' -- an integer handle for a PAPI Event Set as created by PAPI_create_eventset.
''EventCode'' -- a defined event such as PAPI_TOT_INS. 
''*EventCode'' – address of an array of defined events. 
''number'' -- an integer indicating the number of events in the array ''*''''EventCode''.

 

PAPI_add_event adds a single hardware event to a PAPI event set.

PAPI_add_events does the same as PAPI_add_event, but for an array of hardware event codes.

In the following code example, the preset event, PAPI_TOT_INS is added to an event set:

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

main()
{
int EventSet = PAPI_NULL;
int retval;

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

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

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

/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
  handle_error(1);
}
 



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


STARTING, READING, ADDING, AND STOPPING EVENTS IN AN EVENT SET

Hardware events in an event set can be started, read, added, and stopped by calling the following low-level functions, respectively:

C:

 
PAPI_start(''EventSet'')
PAPI_read(''EventSet, *values'')
PAPI_accum(''EventSet'', ''*values'')
PAPI_stop(''EventSet, *values'')

 

Fortran:

 
PAPIF_start(''EventSet,'' check)
PAPIF_read(''EventSet, values,'' check)
PAPIF_accum(''EventSet'', ''values'', check)
PAPIF_stop(''EventSet, values,'' check)

 


ARGUMENTS
 
''EventSet'' -- an integer handle for a PAPI Event Set as created by PAPI_create_eventset.
''*values'' -- an array to hold the counter values of the counting events.

 

PAPI_start starts the counting events in a previously defined event set.

PAPI_read reads (copies) the counters of the indicated event set into the array, values. The counters are left counting after the read without resetting.

PAPI_accum adds the counters of the indicated event set into the array, values. The counters are reset and left counting after the call of this function.

PAPI_stop stops the counting events in a previously defined event set and returns the current events.

The following is a code example of using PAPI_start to start the counting of events in an event set, PAPI_read to read the counters of the same event set into the array values, and PAPI_stop to stop the counting of events in the event set:

 
#include <papi.h>
#include <stdio.h>
    
main()
{
int retval, EventSet = PAPI_NULL;
long_long values[1];

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

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

/* Create the Event Set */
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
    handle_error(1);

/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
    handle_error(1);

/* Start counting */
if (PAPI_start(EventSet) != PAPI_OK)
    handle_error(1);

/* Do some computation here */

if (PAPI_read(EventSet, values) != PAPI_OK)
    handle_error(1);

/* Do some computation here */

if (PAPI_stop(EventSet, values) != PAPI_OK)
    handle_error(1);
}
 


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



RESETTING EVENTS IN AN EVENT SET

The hardware event counts in an event set can be reset to zero by calling the following low-level function:

C:

 
PAPI_reset(''EventSet'')

 

Fortran:

 
PAPI_reset(''EventSet'', check)

 


ARGUMENT

EventSet -- an integer handle for a PAPI event set as created by PAPI_create_eventset.

For example, the EventSet in the code example of the previous section could have been reset to zero by adding the following lines:

 
if (PAPI_reset(EventSet) != PAPI_OK)
  handle_error(1);

 

On success, this function returns PAPI_OK and on error, a non-zero error code is returned.


REMOVING EVENTS IN AN EVENT SET

A hardware event and an array of hardware events can be removed from an event set by calling the following low-level functions, respectively:

C:

 
PAPI_remove_event(''EventSet'', ''EventCode'')


  <pre> 
PAPI_remove_events(''EventSet'', ''EventCode'', ''number'')

 

Fortran:

 
PAPIF_remove_event(''EventSet'', ''EventCode'', check)
PAPIF_remove_events(''EventSet'', ''EventCode'', ''number'', check)

 


ARGUMENTS
 
''EventSet'' -- an integer handle for a PAPI event set as created by PAPI_create_eventset.
''EventCode'' -- a defined event such as PAPI_TOT_INS or a native event. 
''*EventCode'' -- an array of defined events.
''number'' -- an integer indicating the number of events in the array ''*EventCode''.

 

PAPI_remove_event removes a single hardware event from a PAPI event set.

PAPI_remove_events, does the same as PAPI_remove_event, but for an array of hardware event codes.

In the following code example, PAPI_remove_event is used to remove the event, PAPI_TOT_INS, from an event set:

 
#include <papi.h>
#include <stdio.h>
main()
{
int retval, EventSet = PAPI_NULL;

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

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

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

/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
  handle_error(1);

/* Remove event */
if (PAPI_remove_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
  handle_error(1);
}
 


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


EMPTYING AND DESTROYING AN EVENT SET

All the events in an event set can be emptied and destroyed by calling the following low-level functions, respectively:

C:

 
PAPI_cleanup_eventset(''EventSet'')
PAPI_destroy_eventset(''EventSet'')

 

Fortran:

 
PAPIF_cleanup_eventset(''EventSet'', check)
PAPIF_destroy_eventset(''EventSet'', check)

 


ARGUMENT

EventSet -- an integer handle for a PAPI event set as created by PAPI_create_eventset.

Note that the event set must be empty in order to use'PAPI_destroy_eventset'.

In the following code example, PAPI_cleanup_eventset is used to empty all the events from an event set and PAPI_remove_eventset is used to deallocate the memory associated with the empty event set:

 
#include <papi.h>
#include <stdio.h>
   
main()
{
int retval, EventSet = PAPI_NULL;

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

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

/* Create the EventSet */ 
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
    handle_error(1);

/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(&EventSet, PAPI_TOT_INS) != PAPI_OK)
    handle_error(1);

/* Remove all events in the eventset */
if (PAPI_cleanup_eventset(&EventSet) != PAPI_OK)
  handle_error(1);

/* Free all memory and data structures, EventSet must be empty. */
if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
  handle_error(1);
}
 


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


THE STATE OF AN EVENT SET

The counting state of an Event Set can be obtained by calling the following low-level function:

C:

 
PAPI_state(''EventSet, *status'')
	
 

Fortran:

 
PAPIF_state(''EventSet'', ''status'', check)

 


ARGUMENTS

EventSet -- an integer handle for a PAPI event set as created by PAPI_create_eventset.

status -- an integer containing a Boolean combination of one or more of the following nonzero constants as defined in the PAPI header file, papi.h:

PAPI_STOPPED EventSet is stopped
PAPI_RUNNING EventSet is running
PAPI_PAUSED EventSet temporarily disabled by the library
PAPI_NOT_INIT EventSet defined, but not initialized
PAPI_OVERFLOWING EventSet has overflow enabled
PAPI_PROFILING EventSet has profiling enabled
PAPI_MULTIPLEXING EventSet has multiplexing enabled
PAPI_ATTACHED EventSet is attached to another thread/process


In the following code example, PAPI_state is used to return the counting state of an EventSet:

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

main ()
{
int retval, status = 0, EventSet = PAPI_NULL;

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

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

/* Create the EventSet */
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
  handle_error(1);

/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(&EventSet, PAPI_TOT_INS) != PAPI_OK)
  handle_error(1);

/* Start counting */
if (PAPI_state(EventSet, &status) != PAPI_OK)
  handle_error(1);

printf("State is now %d\n", status);

if (PAPI_start(EventSet) != PAPI_OK)
  handle_error(1);

if (PAPI_state(EventSet, &status) != PAPI_OK)
  handle_error(1);

printf("State is now %d\n", status);
}
 



OUTPUT:
 
State is now 1
State is now 2
 


On success, this function returns PAPI_OK and on error, a non-zero error code is returned.


GETTING AND SETTING OPTIONS

The options of the PAPI library or a specific event set can be obtained and set by calling the following low-level functions, respectively:

C:

 
PAPI_get_opt(''option'', ''ptr'')
PAPI_set_opt(''option'', ''ptr'')
''''''
 

Fortran:

 
PAPIF_get_clockrate(''clockrate'')
PAPIF_get_domain(''EventSet'', ''domain'', ''mode'', check)
PAPIF_get_granularity(''EventSet'', granularity, ''mode'', check)
PAPIF_get_preload(''preload'', check)

 


ARGUMENTS

option -- is an input parameter describing the course of action. The Fortran calls are implementations of specific options. Possible values are defined in papi.h and briefly described below:

Option name Explanation
General information requests
PAPI_CLOCKRATE Get clockrate in MHz.
PAPI_MAX_CPUS Get number of CPUs.
PAPI_MAX_HWCTRS Get number of counters.
PAPI_EXEINFO Get Executable addresses for text/data/bss.
PAPI_HWINFO Get information about the hardware.
PAPI_SHLIBINFO Get shared library information used by the program.
PAPI_SUBSTRATEINFO Get the PAPI features the substrate supports.
PAPI_LIB_VERSION Get the full PAPI version of the library.
PAPI_PRELOAD Get ‘‘LD_PRELOAD’’ environment equivalent.
Defaults for the global library
PAPI_DEFDOM Get/Set the default counting domain for newly created event sets.
PAPI_DEFGRN Get/Set the default counting granularity.
PAPI_DEBUG Get/Set the PAPI debug state and the debug handler. The available debug states are defined in papi.h. The debug state is available in ptr->debug.level. The debug handler is available in ptr->debug.handler. For information regarding the behavior of the handler, please see the man page for PAPI_set_debug.
Multiplexing control
PAPI_ MULTIPLEX Get/Set options for multiplexing.
PAPI_MAX_MPX_CTRS Get maximum number of multiplexing counters.
PAPI_DEF_MPX_USEC Get/Set the sampling time slice in microseconds for multiplexing.
Manipulating individual event sets
PAPI_ATTACH Get thread or process id to which event set is attached. Returns TRUE if currently attached. Set event set specified in ptr->ptr->attach.eventset to be attached to thread or process id specified in in ptr->attach.tid.
PAPI_DETACH Get thread or process id to which event set is attached. Returns TRUE if currently detached. Set event set specified in ptr->ptr->attach.eventset to be detached from any thread or process id.
PAPI_DOMAIN Get/Set domain for a single event set. The event set is specified in ptr->domain.eventset
PAPI_GRANUL Get/Set granularity for a single event set. The event set is specified in ptr->granularity.eventset. Currently unimplemented.
Platform Specific Options
PAPI_DATA_ADDRESS Set data address range to restrict event counting for event set specified in ptr->addr.eventset. Starting and ending addresses are specified in ptr->addr.start and ptr->addr.end, respectively. If exact addresses cannot be instantiated, offsets are returned in ptr->addr.start_off and ptr->addr.end_off. Currently implemented on Itanium only.
PAPI_INSTR_ADDRESS Set instruction address range as described above. Itanium only.
 
ptr         -- is a pointer to a structure that acts as both an input and output parameter.
               It is defined in papi.h and below. 
EventSet    -- input; a reference to an EventSetInfo structure 
clockrate   -- output; cycle time of this CPU in MHz; *may* be an estimate generated 
               at init time with a quick timing routine 
domain      -- output; execution domain for which events are counted 
granularity -- output; execution granularity for which events are counted 
mode        -- input; determines if domain or granularity are default or for the 
               current event set 
preload     -- output; environment variable string for preloading libraries 
 

PAPI_get_opt and PAPI_set_opt query or change the options of the PAPI library or a specific event set created by PAPI_create_eventset. In the C interface, these functions pass a pointer to the PAPI_option_t structure. Not all options require or return information in this structure. The Fortran interface is a series of calls implementing various subsets of the C interface. Not all options in C are available in Fortran.

Note that a number of options are available as separate entry points in both C and Fortran. This can make calling sequences simpler. Calls that are simply wrappers to PAPI_get_opt and PAPI_set_opt are listed below:

PAPI_get_executable_info Get the executable’s address space information.
PAPI_get_hardware_info Get information about the system hardware.
PAPI_get_multiplex Get the multiplexing status of specified event set.
PAPI_get_shared_lib_info Get information about the shared libraries used by the process.
PAPI_get_substrate_info Get information about the substrate features.
PAPI_set_debug Set the current debug level for PAPI.
PAPI_set_domain Set the default execution domain for new event sets.
PAPI_set_granularity Get/Set the default granularity for new event sets.
PAPI_set_multiplex Convert a standard event set to a multiplexed event set.


The PAPI_option_t structure is actually a union of structures that provide specific information for each of the options defined in the table above. This union is defined as shown below:

 
   typedef union {
      PAPI_preload_info_t preload;
      PAPI_debug_option_t debug;
      PAPI_granularity_option_t granularity;
      PAPI_granularity_option_t defgranularity;
      PAPI_domain_option_t domain;
      PAPI_domain_option_t defdomain;
      PAPI_attach_option_t attach;
      PAPI_multiplex_option_t multiplex;
      PAPI_hw_info_t *hw_info;
      PAPI_shlib_info_t *shlib_info;
      PAPI_exe_info_t *exe_info;
      PAPI_substrate_info_t *sub_info;
      PAPI_addr_range_option_t addr;
   } PAPI_option_t;
 


Each of these individual structures, as defined in papi.h, is shown below:

'For'PAPI_PRELOAD:

 
   typedef struct _papi_preload_option {
      char lib_preload_env[PAPI_MAX_STR_LEN];   
      char lib_preload_sep;
      char lib_dir_env[PAPI_MAX_STR_LEN];
      char lib_dir_sep;
   } PAPI_preload_info_t;
 

'For'PAPI_DEBUG:

 
   typedef int (*PAPI_debug_handler_t) (int code);

   typedef struct _papi_debug_option {
      int level;
      PAPI_debug_handler_t handler;
   } PAPI_debug_option_t;
 

'For'PAPI_DEFGRN'and'PAPI_GRANUL:

 
   typedef struct _papi_granularity_option {
      int eventset;
      int granularity;
   } PAPI_granularity_option_t;
 

'For'PAPI_DEFDOM'and'PAPI_DOMAIN:

 
   typedef struct _papi_domain_option {
      int eventset;
      int domain;
   } PAPI_domain_option_t;
 

'For'PAPI_ATTACH'and'PAPI_DETACH:

 
   typedef struct _papi_attach_option {
      int eventset;
      unsigned long tid;
   } PAPI_attach_option_t;
 

For'PAPI_MULTIPLEX'and'''''''PAPI_DEF_MPX_USEC':

 
   typedef struct _papi_multiplex_option {
      int eventset;
      int us;
      int flags;
   } PAPI_multiplex_option_t;
 

'For'PAPI_HWINFO:

 
   typedef struct _papi_hw_info {
      int ncpu;                 /* Number of CPU's in an SMP Node */
      int nnodes;               /* Number of Nodes in the entire system */
      int totalcpus;            /* Total number of CPU's in the entire system */
      int vendor;               /* Vendor number of CPU */
      char vendor_string[PAPI_MAX_STR_LEN];     /* Vendor string of CPU */
      int model;                /* Model number of CPU */
      char model_string[PAPI_MAX_STR_LEN];      /* Model string of CPU */
      float revision;           /* Revision of CPU */
      float mhz;                /* Cycle time of this CPU */
      PAPI_mh_info_t mem_hierarchy;  /* PAPI memory heirarchy description */
   } PAPI_hw_info_t;
 

For'PAPI_SHLIBINFO'and'''''''PAPI_EXEINFO':

 
   typedef struct _papi_address_map {
      char name[PAPI_HUGE_STR_LEN];
      caddr_t text_start;       /* Start address of program text segment */
      caddr_t text_end;         /* End address of program text segment */
      caddr_t data_start;       /* Start address of program data segment */
      caddr_t data_end;         /* End address of program data segment */
      caddr_t bss_start;        /* Start address of program bss segment */
      caddr_t bss_end;          /* End address of program bss segment */
   } PAPI_address_map_t;
 
 
   typedef struct _papi_shared_lib_info {
      PAPI_address_map_t *map;
      int count;
   } PAPI_shlib_info_t;
 
 
   typedef struct _papi_program_info {
      char fullname[PAPI_HUGE_STR_LEN];  /* path+name */
      PAPI_address_map_t address_info;
   } PAPI_exe_info_t;
 

'For'PAPI_SUBSTRATEINFO:

 
   typedef struct _papi_substrate_option {
     char name[PAPI_MAX_STR_LEN];    /* Name of the substrate we're using,
                                        usually CVS RCS Id */
     char version[PAPI_MIN_STR_LEN]; /* Version of this substrate,
                                        usually CVS Revision */
     char support_version[PAPI_MIN_STR_LEN]; /* Version of the support library */
     char kernel_version[PAPI_MIN_STR_LEN];  /* Version of the kernel PMC
                                                support driver */
     int num_cntrs;          /* Number of hardware counters substrate supports */
     int num_mpx_cntrs;      /* Number of multiplexed counters the substrate or
                                PAPI supports */
     int num_preset_events;   /* Number of preset events the substrate supports */
     int num_native_events;   /* Number of native events the substrate supports */
     int default_domain;      /* The default domain when this substrate is used */
     int available_domains;   /* Available domains */ 
     int default_granularity; /* Default granularity when this substrate is used */
     int available_granularities; /* Available granularities */
     int multiplex_timer_sig;     /* Signal number used by the multiplex timer,
                                     0 if not */
     int multiplex_timer_num;     /* Number of the itimer or POSIX 1 timer used
                                     by the multiplex timer */
     int multiplex_timer_us;      /* uS between switching of sets */
     int hardware_intr_sig;     /* Signal used by hardware to deliver PMC events */
     int opcode_match_width;    /* Width of opcode matcher if exists, 0 if not */
     int reserved_ints[4];
     unsigned int hardware_intr:1; /* hw overflow intr, does not need to be
                                      emulated in software*/
     unsigned int precise_intr:1;  /* Performance interrupts happen precisely */
     unsigned int posix1b_timers:1;  /* Using POSIX 1b interval timers
                                       (timer_create) instead of setitimer */
     unsigned int kernel_profile:1;   /* Has kernel profiling support (buffered
                                        interrupts or sprofil-like) */
     unsigned int kernel_multiplex:1; /* In kernel multiplexing */
     unsigned int data_address_range:1; /* Supports data address range limiting */
     unsigned int instr_address_range:1; /* Supports instruction address range
                                            limiting */
     unsigned int fast_counter_read:1;   /* Supports user level PMC read
                                            instruction */
     unsigned int fast_real_timer:1;     /* Supports a fast real timer */
     unsigned int fast_virtual_timer:1;  /* Supports a fast virtual timer */
     unsigned int attach:1;		     /* Supports attach */
     unsigned int attach_must_ptrace:1;  /* Attach must first ptrace and 
                                            stop the thread/process*/
     unsigned int edge_detect:1;         /* Supports edge detection on events */
     unsigned int invert:1;              /* Supports invert detection on events */
     unsigned int profile_ear:1;         /* Supports data/instr/tlb miss
                                            address sampling */
     unsigned int grouped_cntrs:1;   /* Underlying hardware uses counter groups */
     unsigned int reserved_bits:16;
   } PAPI_substrate_info_t;
 

For'PAPI_DATA_ADDRESS'and'''''''PAPI_INSTR_ADDRESS':

 
   /* address range specification for range restricted counting */
   typedef struct _papi_addr_range_option { /* if both are zero, range disabled */
      int eventset;           /* eventset to restrict */
      caddr_t start;          /* user requested start address of address range */
      caddr_t end;            /* user requested end address of an address range */
      int start_off;          /* hardware specified offset from start address */
      int end_off;            /* hardware specified offset from end address */
   } PAPI_addr_range_option_t;
 


The file, papi.h, contains current definitions for the structures unioned in the PAPI_option_t structure. Users should refer to papi.h for specifics on the use of fields in these structures.

In the following code example, PAPI_get_opt is used to acquire the option, PAPI_MAX_HWCTRS, of an event set and PAPI_set_opt is used to set the option, PAPI_DOMAIN, to the same event set:

 
#include <papi.h>
#include <stdio.h>
 
main()
{
int num, retval, EventSet = PAPI_NULL;
PAPI_option_t options;
 
/* Initialize the PAPI library */
retval = PAPI_library_init(PAPI_VER_CURRENT);
 
if (retval != PAPI_VER_CURRENT) {
  fprintf(stderr, "PAPI library init error!\n");
  exit(1);
}
 
if ((num = PAPI_get_opt(PAPI_MAX_HWCTRS,NULL)) <= 0)
  handle_error();
 
printf("This machine has %d counters.0,num);
 
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
  handle_error();
 
/* Set the domain of this EventSet
   to counter user and kernel modes for this
   process */
        
memset(&options,0x0,sizeof(options));
 
options.domain.eventset = EventSet;
options.domain.domain = PAPI_DOM_ALL;
if (PAPI_set_opt(PAPI_DOMAIN, &options) != PAPI_OK)
  handle_error();
}
 
POSSIBLE OUTPUT (VARIES ON DIFFERENT PLATFORMS):
 
This machine has 4 counters.
 

'

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

For more code examples, see ctests/second.c or ctests/third.c in the PAPI source distribution.


SIMPLE CODE EXAMPLES

HIGH-LEVEL API

The following is a simple code example of using the high-level API:

 
#include <papi.h>

#define NUM_FLOPS 10000
#define NUM_EVENTS 1

main()
{
int Events[NUM_EVENTS] = {PAPI_TOT_INS};
long_long values[NUM_EVENTS];

/* Start counting events */
if (PAPI_start_counters(Events, NUM_EVENTS) != PAPI_OK)
   handle_error(1);

/* Defined in tests/do_loops.c in the PAPI source distribution */
do_flops(NUM_FLOPS);

/* Read the counters */
if (PAPI_read_counters(values, NUM_EVENTS) != PAPI_OK)
   handle_error(1);

printf("After reading the counters: %lld\n",values[0]);

do_flops(NUM_FLOPS);

/* Add the counters */
if (PAPI_accum_counters(values, NUM_EVENTS) != PAPI_OK)
   handle_error(1);
printf("After adding the counters: %lld\n", values[0]);

do_flops(NUM_FLOPS);

/* Stop counting events */
if (PAPI_stop_counters(values, NUM_EVENTS) != PAPI_OK)
   handle_error(1);

printf("After stopping the counters: %lld\n", values[0]);
}
 



POSSIBLE OUTPUT:
 
After reading the counters: 441027
After adding the counters: 891959
After stopping the counters: 443994
 

'

Notice that on the second line (after adding the counters) the value is approximately twice as large as the first line (after reading the counters) because PAPI_read_counters resets and leaves the counters running, then PAPI_accum_counters adds the value of the current counter into the values array.


LOW-LEVEL API

The following is a simple code example that applies the same technique as the above example, except it uses the Low-Level API:

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

#define NUM_FLOPS 10000

main()
{
int retval, EventSet=PAPI_NULL;
long_long values[1];

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

/* Create the Event Set */
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
    handle_error(1);

/* Add Total Instructions Executed to our Event Set */
if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
    handle_error(1);

/* Start counting events in the Event Set */
if (PAPI_start(EventSet) != PAPI_OK)
    handle_error(1);

/* Defined in tests/do_loops.c in the PAPI source distribution */
do_flops(NUM_FLOPS);

/* Read the counting events in the Event Set */
if (PAPI_read(EventSet, values) != PAPI_OK)
    handle_error(1);

printf("After reading the counters: %lld\n",values[0]);

/* Reset the counting events in the Event Set */
if (PAPI_reset(EventSet) != PAPI_OK)
  handle_error(1);

do_flops(NUM_FLOPS);

/* Add the counters in the Event Set */
if (PAPI_accum(EventSet, values) != PAPI_OK)
   handle_error(1);
printf("After adding the counters: %lld\n",values[0]);

do_flops(NUM_FLOPS);

/* Stop the counting of events in the Event Set */
if (PAPI_stop(EventSet, values) != PAPI_OK)
    handle_error(1);

printf("After stopping the counters: %lld\n",values[0]);
}
 




POSSIBLE OUTPUT:
 
After reading the counters: 440973
After adding the counters: 882256
After stopping the counters: 443913
 

'

Notice that in order to get the desired results (the second line approximately twice as large as the first line), PAPI_reset was called to reset the counters, since PAPI_read did not reset the counters.