Timing

Sections of code can be timed using sdp_Timer.

For more comprehensive timing and automatic reporting, use the timer hierarchy provided by sdp_Timers.

Include the header “ska-sdp-func/utility/sdp_timer.h” to use these functions.

Structures

struct sdp_Timer
#include “ska-sdp-func/utility/sdp_timer.h”

Provides a basic timer.

Call sdp_timer_create() to create a timer. The timer is created in a paused state.

To resume the timer, pause the timer, or find the current elapsed time, call sdp_timer_resume(), sdp_timer_pause() or sdp_timer_elapsed(), respectively.

Release memory used by the timer by calling sdp_timer_free().

struct sdp_TimerNode
#include “ska-sdp-func/utility/sdp_timer.h”

Internal data used to create a timer hierarchy.

struct sdp_Timers
#include “ska-sdp-func/utility/sdp_timer.h”

Provides a timer hierarchy.

Use sdp_timers_push() to start timing a section of code until the next sdp_timers_pop(). The elapsed time will be reported using the name supplied to sdp_timers_push(). If a timer already exists with that name, the elapsed time will be added to that timer, otherwise a new timer will be created.

Use sdp_timers_pop_push() to pause the current timer and start another.

Use sdp_timers_report() to print out a timing report for all the timers in the hierarchy.

Using the macros SDP_TMR_CREATE(), SDP_TMR_PUSH(), SDP_TMR_POP(), SDP_TMR_POP_PUSH(), SDP_TMR_REPORT() may be clearer and more convenient in many cases. The macro SDP_TMR_HANDLE can be used to obtain the name of the handle to the timer hierarchy returned in SDP_TMR_CREATE().

Call sdp_timers_free() or SDP_TMR_FREE() to release memory held by the timer hierarchy.

For example:

sdp_Timers* timers = sdp_timers_create(
        "A collection of timers", SDP_TIMER_NATIVE, 1
);

sdp_timers_push(timers, "Doing something", 0, 0);
do_something_that_takes_a_while();

sdp_timers_pop_push(timers, "Doing something else", 0, 0);
do_something_else_that_takes_a_while();
sdp_timers_pop(timers, 0, 0);

sdp_timers_report(timers, __func__, FILENAME, __LINE__);
sdp_timers_free(timers);

Or, equivalently:

SDP_TMR_CREATE("A collection of timers", SDP_TIMER_NATIVE, 1);

SDP_TMR_PUSH("Doing something");
do_something_that_takes_a_while();

SDP_TMR_POP_PUSH("Doing something else");
do_something_else_that_takes_a_while();
SDP_TMR_POP;

SDP_TMR_REPORT;
SDP_TMR_FREE;

In a multi-threaded environment, each thread will need its own timer. Before starting the threads, call sdp_timers_create_set(), specifying the name of the timer and the number of threads it will be accessed from, to allocate a slot for each. Then supply the thread ID in relevant calls to sdp_timers_push() and sdp_timers_pop(). In a single-threaded environment, the state can be managed internally, but when using multiple threads, the state is returned to the caller and must be explicitly passed.

For example:

SDP_TMR_CREATE("A collection of timers", SDP_TIMER_NATIVE, num_threads);
SDP_TMR_CREATE_SET("Doing something", num_threads);

// In multi-threaded code:
sdp_TimerNode* node = SDP_TMR_ROOT;
node = sdp_timers_push(SDP_TMR_HANDLE, "Doing something", thread_id, node);
do_something_that_takes_a_while();
node = sdp_timers_pop(SDP_TMR_HANDLE, thread_id, node);

// In single-threaded code:
SDP_TMR_PUSH("Doing something else");
do_something_else_that_takes_a_while();
SDP_TMR_POP;

SDP_TMR_REPORT;
SDP_TMR_FREE;

The minimum, maximum, median and interquartile range is reported for all timer names which have multiple index values.

enum sdp_TimerType

Values:

enumerator SDP_TIMER_NATIVE
enumerator SDP_TIMER_CUDA

Functions

sdp_Timer *sdp_timer_create(sdp_TimerType type)

Creates a timer.

The timer is created in a paused state.

The type parameter may take the values:

  • SDP_TIMER_NATIVE

  • SDP_TIMER_CUDA

These timers are used to measure performance of, respectively, native code, or CUDA kernels.

Parameters:

type – Type of timer to create.

Returns:

Pointer to created timer.

void sdp_timer_free(sdp_Timer *timer)

Destroys the timer.

Parameters:

timer – Pointer to timer.

double sdp_timer_elapsed(sdp_Timer *timer)

Returns the total elapsed time since starting the timer, in seconds.

Parameters:

timer – Pointer to timer.

Returns:

The number of seconds since the timer was started.

void sdp_timer_pause(sdp_Timer *timer)

Pauses the timer.

Parameters:

timer – Pointer to timer.

void sdp_timer_reset(sdp_Timer *timer)

Resets a timer back to its initial state.

The timer is zeroed and paused.

Parameters:

timer – Pointer to timer.

void sdp_timer_resume(sdp_Timer *timer)

Resumes the timer from a paused state.

Parameters:

timer – Pointer to timer.

void sdp_timer_restart(sdp_Timer *timer)

Restarts the timer.

Parameters:

timer – Pointer to timer.

void sdp_timer_start(sdp_Timer *timer)

Starts and resets the timer, clearing the current elapsed time.

Parameters:

timer – Pointer to timer.

sdp_Timers *sdp_timers_create(const char *name, sdp_TimerType type, int num_threads)

Creates a new timer hierarchy with the given name.

See also SDP_TMR_CREATE()

Parameters:
  • name – String to display at the root of the timer hierarchy.

  • type – Enumerated type of timers to create.

  • num_threads – Number of threads to display next to name string.

Returns:

Pointer to timer hierarchy.

void sdp_timers_free(sdp_Timers *timers)

Destroys the timer hierarchy.

See also SDP_TMR_FREE

Parameters:

timers – Pointer to timer hierarchy.

sdp_TimerNode *sdp_timers_create_set(sdp_Timers *timers, const char *name, int num, sdp_TimerNode *parent)

Allocate slots for multiple timers of the given name.

This is only required for timers in regions with multiple threads. Call this before entering the parallel region.

See also SDP_TMR_CREATE_SET()

Parameters:
  • timers – Pointer to timer hierarchy.

  • name – Name of timer node to create.

  • num – Number of timer slots to create on the node (one per thread).

  • parent – Optional pointer to timer’s parent node. If NULL, this is taken from the current internal state.

Returns:

A pointer to the (new) timer node.

sdp_TimerNode *sdp_timers_pop(sdp_Timers *timers, int idx, sdp_TimerNode *timer)

Pause the current timer.

This should be called after a call to sdp_timers_push().

The internal state will be updated unless timer is specified. Note that this is only thread safe when timer is non-NULL.

See also SDP_TMR_POP

Parameters:
  • timers – Pointer to timer hierarchy.

  • idx – Index of timer to pause.

  • timer – Optional pointer to timer node. If NULL, this is taken from the current internal state.

Returns:

If timer was specified, a pointer to the timer’s parent node.

sdp_TimerNode *sdp_timers_push(sdp_Timers *timers, const char *name, int idx, sdp_TimerNode *parent)

Resumes the named timer, creating it first if necessary.

The timer will be created as a child of the specified parent, or as a child of the current timer if parent is not specified. The internal state will be updated unless parent is specified. Note that this is only thread safe when parent is non-NULL.

See also SDP_TMR_PUSH()

Parameters:
  • timers – Pointer to timer hierarchy.

  • name – Name of timer node.

  • idx – Index of timer to resume.

  • parent – Optional pointer to the timer’s parent node. If NULL, this is taken from the current internal state.

Returns:

If parent was specified, a pointer to the timer node.

sdp_TimerNode *sdp_timers_pop_push(sdp_Timers *timers, const char *name, int idx, sdp_TimerNode *timer)

Calls sdp_timers_pop() followed by sdp_timers_push().

The internal state will be updated unless timer is specified. Note that this is only thread safe when timer is non-NULL.

See also SDP_TMR_POP_PUSH()

Parameters:
  • timers – Pointer to timer hierarchy.

  • name – Name of timer node.

  • idx – Index of timer to pause and resume.

  • timer – Optional pointer to current timer node. If NULL, this is taken from the current internal state.

Returns:

If timer was specified, a pointer to the timer node.

void sdp_timers_report(const sdp_Timers *timers, const char *func, const char *file, int line)

Print a timing report from all timers.

See also SDP_TMR_REPORT

Parameters:
  • timers – Pointer to timer hierarchy.

  • func – Function name to print in log messages.

  • file – File name to print in log messages.

  • line – Line number to print in log messages.

sdp_TimerNode *sdp_timers_root(sdp_Timers *timers)

Return a pointer to the timer hierarchy’s root node.

See also SDP_TMR_ROOT

Parameters:

timers – Pointer to timer hierarchy.

Returns:

A pointer to the root node.

SDP_TMR_HANDLE

Convenience macro to return the handle to the timer hierarchy.

SDP_TMR_CREATE(NAME, TYPE, NUM_THREADS)

Convenience macro which calls sdp_timers_create().

SDP_TMR_CREATE_SET(NAME, NUM_THREADS)

Convenience macro which calls sdp_timers_create_set().

SDP_TMR_FREE

Convenience macro which calls sdp_timers_free().

SDP_TMR_PUSH(NAME)

Convenience macro which calls sdp_timers_push().

SDP_TMR_POP_PUSH(NAME)

Convenience macro which calls sdp_timers_pop_push().

SDP_TMR_POP

Convenience macro which calls sdp_timers_pop().

SDP_TMR_REPORT

Convenience macro which calls sdp_timers_report().

SDP_TMR_ROOT

Convenience macro which calls sdp_timers_root().