Skip to content

PAPI Timers

Treece-Burgess edited this page Jan 28, 2024 · 15 revisions

PAPI Timers

PAPI timers use the most accurate timers available on the platform in use. These timers can be used to obtain both real and virtual time on each supported platform. The real time clock runs all the time (e.g. a wall clock) and the virtual time clock runs only when the processor is running in user mode.

Real Time

Real time can be acquired in clock cycles and microseconds by calling the following low-level functions, respectively:

C:

long long retval = PAPI_get_real_cyc();

No arguments for PAPI_get_real_cyc.

long long retval = PAPI_get_real_usec();

No arguments for PAPI_get_real_usec.

Fortran:

use iso_c_binding
integer(c_long_long) real_cyc
call PAPIF_get_real_cyc(real_cyc)

Fortran arguments for PAPIF_get_real_cyc:

  • real_cyc -- stores real time counter value in clock cycles.
use iso_c_binding
integer(c_long_long) time
call PAPIF_get_real_usec(time)

Fortran arguments for PAPIF_get_real_usec:

  • time -- stores real time counter value in microseconds.

Both of these functions return the total real time passed since some arbitrary starting point and are equivalent to wall clock time. Also, these functions always succeed (error-free) since they are guaranteed to exist on every PAPI supported platform.

In the following code example, PAPI_get_real_cyc and PAPI_get_real_usec are used to obtain the real time it takes to create an event set in clock cycles and microseconds, respectively:

#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;
    long long start_cycles, end_cycles, start_usec, end_usec;

    retval = PAPI_library_init(PAPI_VER_CURRENT);
    if (retval != PAPI_VER_CURRENT)
        handle_error(retval);
			
    /* Gets the starting time in clock cycles */
    start_cycles = PAPI_get_real_cyc();
			
    /* Gets the starting time in microseconds */
    start_usec = PAPI_get_real_usec();
			
    /*Create an EventSet */
    retval = PAPI_create_eventset(&EventSet);
    if (retval != PAPI_OK)
        handle_error(retval);

    /* Gets the ending time in clock cycles */
    end_cycles = PAPI_get_real_cyc();
			
    /* Gets the ending time in microseconds */
    end_usec = PAPI_get_real_usec();
			
    printf("Wall clock cycles: %lld\n", end_cycles - start_cycles);
    printf("Wall clock time in microseconds: %lld\n", end_usec - start_usec);

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

Possible Output

Wall clock cycles: 100173
Wall clock time in microseconds: 136


PASSED

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

Virtual Time

Virtual time can be acquired in clock cycles and microseconds by calling the following low-level functions, respectively:

C:

long long retval = PAPI_get_virt_cyc();

No arguments for PAPI_get_virt_cyc.

long long retval = PAPI_get_virt_usec();

No arguments for PAPI_get_virt_usec.

Fortran:

use iso_c_binding
integer(c_long_long) virt_cyc
call PAPIF_get_virt_cyc(virt_cyc)

Fortran arguments for PAPIF_get_virt_cyc:

  • virt_cyc -- stores virtual time counter value in clock cycles.
use iso_c_binding
integer(c_long_long) time
call PAPIF_get_virt_usec(time)

Fortran arguments for PAPIF_get_virt_usec:

  • time -- stores virtual time counter value in microseconds.

As a note, make sure to initialize the PAPI library to use PAPI_get_virt_cyc and PAPIF_get_virt_cyc.

Both of these functions return the total number of virtual units from some arbitrary starting point. Virtual units accrue every time a process is running in user-mode. Like the real time counters, these functions always succeed (error-free) since they are guaranteed to exist on every PAPI supported platform. However, the resolution can be as bad as 1/Hz as defined by the operating system on some platforms.

In the following code example, PAPI_get_virt_cyc and PAPI_get_virt_usec are used to obtain the virtual time it takes to create an event set in clock cycles and microseconds, respectively:

#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;
    long long start_cycles, end_cycles, start_usec, end_usec;

    retval =  PAPI_library_init(PAPI_VER_CURRENT);   
    if (retval != PAPI_VER_CURRENT)
	handle_error(retval);
			
    /* Gets the starting time in clock cycles */
    start_cycles = PAPI_get_virt_cyc();
			
    /* Gets the starting time in microseconds */
    start_usec = PAPI_get_virt_usec();
			
    /*Create an EventSet */
    retval = PAPI_create_eventset(&EventSet);
    if (retval != PAPI_OK)
	handle_error(retval);

    /* Gets the ending time in clock cycles */
    end_cycles = PAPI_get_virt_cyc();
			
    /* Gets the ending time in microseconds */
    end_usec = PAPI_get_virt_usec();
			
    printf("Virtual clock cycles: %lld\n", end_cycles - start_cycles);
    printf("Virtual clock time in microseconds: %lld\n", end_usec - start_usec);

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

Possible Output

Virtual clock cycles: 715408
Virtual clock time in microseconds: 976


PASSED

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