PAPIC:High Level
From PAPIDocs
Jump to: navigation, search

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 on the cpu component. 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. 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.

The eight functions in the high-level API as shown in the table below. They allow the user to access and count specific hardware events from both C and Fortran.

Function name Description
PAPI_num_counters get the number of hardware counters available on the system
PAPI_flips simplified call to get Mflips/s (floating point instruction rate), real and processor time
PAPI_flops simplified call to get Mflops/s (floating point operation rate), real and processor time
PAPI_ipc gets instructions per cycle, real and processor time
PAPI_accum_counters add current counts to array and reset counters
PAPI_read_counters copy current counts to array and reset counters
PAPI_start_counters start counting hardware events
PAPI_stop_counters stop counters and return current counts

See the example code below, or src/ctests/high-level.c in the PAPI source distribution for examples using the high level API.

Initializing the High Level API

Note that the high-level interface is self-initializing. You can mix high and low level calls, but you must call either PAPI_library_init or a high level routine before calling a low level routine.

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 initialize 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

(results vary 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 mathematical floating point operation.

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.

High Level Code Example

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.