|
  Counter Interfaces
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ViewsFrom PAPIDocs
PAPI’S COUNTER INTERFACESHIGH-LEVEL APIWHAT 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 APIThe 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 CALLSThree 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 COUNTERSCounters 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 APIWHAT 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 APIThe 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)
ARGUMENTversion -- 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.0PAPI Version Number MAJOR: 3 MINOR: 5 REVISION: 0
EVENT SETSWHAT 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 SETAn event set can be created by calling the following the low-level function: C:
PAPI_create_eventset (''*EventSet'')
Fortran:
PAPIF_create_eventset(''EventSet, ''check)
ARGUMENTEventSet -- 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 SETHardware 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 SETHardware 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 SETThe 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)
ARGUMENTEventSet -- 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 SETA 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 SETAll 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)
ARGUMENTEventSet -- 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 SETThe 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)
ARGUMENTSEventSet -- 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:
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 OPTIONSThe 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)
ARGUMENTSoption -- 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:
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:
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;
'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;
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 EXAMPLESHIGH-LEVEL APIThe 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 APIThe 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. |