ConfigManager API reference

Caliper provides several built-in performance measurement and reporting configurations. These can be activated from within a program with the ConfigManager API using a short configuration string. Configuration strings can be hard-coded in the program or provided by the user in some form, e.g. as a command-line parameter or in the programs’s configuration file.

To access and control the built-in configurations, create a cali::ConfigManager object. Add a configuration string with add(), start the requested configuration channels with start(), and trigger output with flush():

#include <caliper/cali-manager.h>

int main(int argc, char* argv[])
{
   cali::ConfigManager mgr;

   if (argc > 1)
      mgr.add(argv[1]);
   if (mgr.error())
      std::cerr << "Config error: " << mgr.error_msg() << std::endl;
   // ...
   mgr.start(); // start requested performance measurement channels
   // ... (program execution)
   mgr.flush(); // write performance results
}

API Reference

group ControlChannelAPI

An API for controlling Caliper built-in performance measurement configurations.

The control channel API provides means to access and control built-in Caliper configurations and enable measurements from within a target program.

Functions

std::pair<std::shared_ptr<CollectiveOutputChannel>, std::string> make_collective_output_channel(const char *config_str)

Create a CollectiveOutputChannel object for a ConfigManager configuration.

Returns a CollectiveOutputChannel object, which can be flushed into a user-defined C++ stream, for the ConfigManager configuration in config_str. If multiple configuration channels are given in config_str, only the first one will be used.

Currently, this only works for input configurations that use the mpireport service, such as runtime-report.

The example demonstrates how to collect and write runtime-report output into a user-provided file stream:

#include <caliper/CollectiveOutputChannel.h>

#include <mpi.h>

#include <fstream>
#include <iostream>
#include <tuple>

int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);

    std::shared_ptr<cali::CollectiveOutputChannel> channel;
    std::string errmsg;

    std::tie(channel, errmsg) =
        cali::make_collective_output_channel("runtime-report(profile.mpi)");

    if (!channel) {
        std::cerr << "Error: " << errmsg << std::endl;
        MPI_Abort(MPI_COMM_WORLD, -1);
    }

    channel->start();

    CALI_MARK_BEGIN("work");
    // ...
    CALI_MARK_END("work");

    int rank = 0;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    std::ofstream os;
    if (rank == 0) {
        os.open("report.txt");
    }

    // collective_flush() is collective on MPI_COMM_WORLD
    channel->collective_flush(os, MPI_COMM_WORLD);

    MPI_Finalize();
}

Returns:

A std::pair where the first element is the std::shared_ptr-wrapped CollectiveOutputChannel object for the given configuration. If the std::shared_ptr object is empty, an error occured and the second pair element contains an error message.

void add_global_config_specs(const ConfigManager::ConfigInfo **configs)

Add a set of global ConfigManager configs.

class ChannelController
#include <ChannelController.h>

Base class for Caliper channel controllers.

A channel controller wraps a Caliper configuration and channel. The underlying channel is initially inactive, and will be created in the first call of the start() method. Derived classes can modify the configuration before the channel is created.

ChannelController objects can be copied and moved. The underlying Caliper channel will be deleted when the last ChannelController object referencing is destroyed.

Subclassed by cali::RegionProfile

Public Functions

Channel *channel()

Return the underlying Caliper channel object.

void start()

Create and activate the Caliper channel, or reactivate a stopped Caliper channel.

void stop()

Deactivate the Caliper channel.

bool is_active() const

Returns true if channel exists and is active, false otherwise.

std::string name() const

Returns the name of the underlying channel.

virtual void flush()

Flush the underlying Caliper channel.

Allows derived classes to implement custom Caliper data processing. The base class implementation invokes Caliper::flush_and_write().

config_map_t copy_config() const

Return the underlying config map.

ChannelController(const char *name, int flags, const config_map_t &cfg)

Create channel controller with given name, flags, and config.

class CollectiveOutputChannel
#include <CollectiveOutputChannel.h>

A ChannelController for Caliper configurations that aggregate output over MPI.

A CollectiveOutputChannel provides the collective_flush() interface to produce output in an MPI program via a user-provided MPI communicator and/or C++ I/O stream.

Public Functions

virtual void start() = 0

Start the underlying channel.

virtual void stop() = 0

Stop/pause the underlying channel.

virtual void collective_flush(OutputStream &os, MPI_Comm comm) = 0

Aggregate data from MPI ranks in comm and write it into os.

This is a collective operation on the MPI communicator comm. Rank 0 in comm collects all output, and formats and writes it into os. If comm is MPI_COMM_NULL, the calling process will aggregate and write its local data.

Parameters:
  • os – Output stream object. Used only on rank 0 and ignored on all other ranks.

  • comm – MPI communicator

std::ostream &collective_flush(std::ostream &os, MPI_Comm comm)

Aggregate data from MPI ranks in comm and write it into os.

This is a collective operation on the MPI communicator comm. Rank 0 in comm collects all output, and formats and writes it into os. If comm is MPI_COMM_NULL, the calling process will aggregate and write its local data.

Parameters:
  • os – Output stream object. Used only on rank 0 and ignored on all other ranks.

  • comm – MPI communicator

virtual void collective_flush(MPI_Comm comm)

Aggregate data from MPI ranks in comm and write output.

This is a collective operation on the MPI communicator comm. Rank 0 in comm collects all output, and formats and writes it into an output stream defined by the channel (stdout by default). If comm is MPI_COMM_NULL, the calling process will aggregate and write its local data.

Parameters:

comm – MPI communicator

Public Static Functions

static std::shared_ptr<CollectiveOutputChannel> from(const std::shared_ptr<ChannelController> &from)

Try to create a CollectiveOutputChannel based on the configuration in from.

Can be used to convert a control channel created by ConfigManager into a CollectiveOutputChannel object that can be flushed into a user-defined stream with collective_flush().

Returns:

A new std::shared_ptr-wrapped CollectiveOutputChannel, or an empty std::shared_ptr object if from couldn’t be made into a collective output channel.

class ConfigManager
#include <ConfigManager.h>

Configure, enable, and manage built-in or custom Caliper configurations.

ConfigManager is the principal component for managing Caliper measurement configurations programmatically. It parses a configuration string and creates a set of control channels for the requested measurement configurations, and provides control methods to start, stop, and flush the created measurements channels. Example:

cali::ConfigManager mgr;

//   Add a configuration string creating a runtime report
// and event trace channel
mgr.add("runtime-report,event-trace(output=trace.cali)");

// Check for configuration string parse errors
if (mgr.error()) {
    std::cerr << "ConfigManager: " << mgr.error_msg() << std::endl;
}

// Activate all requested configuration channels
mgr.start();

// ...

//   Trigger output on all configured channel controllers.
// Must be done explicitly, the built-in Caliper configurations do not
// not flush results automatically.
mgr.flush();

ConfigManager provides a set of built-in configurations specifications like “runtime-report”. Users can also add custom specifications with add_config_spec().

Public Types

typedef cali::ChannelController *(*CreateConfigFn)(const char *name, const config_map_t &initial_cfg, const Options &opts)

Callback function to create a custom ChannelController for a config.

Example:

cali::ChannelController* make_controller(const char* name,
        const cali::config_map_t& initial_cfg,
        const cali::ConfigManager::Options& opts)
{
    class MyChannelController : public cali::ChannelController {
    public:
        MyChannelController(const char* name,
                const cali::config_map_t& initial_cfg,
                const cali::ConfigManager::Options& opts)
            : cali::ChannelController(name, 0, initial_cfg)
        {
            opts.update_channel_config(config());
        }
    };

    return new MyChannelController(name, initial_cfg, opts);
}

Param name:

The channel name. Must be passed to the created ChannelController object.

Param initial_cfg:

The initial config map from the config’s JSON spec. Must be passed to the created ChannelController object.

Param opts:

User-requested options for the channel. Invoke Options::update_channel_config(config_map_t&) const on the ChannelController’s config map to apply options.

Return:

A new ChannelController object.

typedef std::string (*CheckArgsFn)(const Options &opts)

Callback function to implement custom options checking for a config spec.

Public Functions

explicit ConfigManager(const char *config_string)

Construct ConfigManager and add the given configuration string.

void add_config_spec(const ConfigInfo &info)

Add a custom config spec to this ConfigManager.

Adds a new Caliper configuration specification for this ConfigManager using a custom ChannelController or option checking function.

void add_config_spec(const char *json)

Add a JSON config spec to this ConfigManager.

Adds a new Caliper configuration specification for this ConfigManager using a basic ChannelController.

This example adds a config spec to perform simple sample tracing:

const char* spec =
  "{"
  " \"name\"        : \"sampletracing\","
  " \"description\" : \"Perform sample tracing\","
  " \"services\"    : [ \"recorder\", \"sampler\", \"trace\" ],"
  " \"config\"      :
  "  { \"CALI_SAMPLER_FREQUENCY\"     : \"100\",  "
  "    \"CALI_CHANNEL_FLUSH_ON_EXIT\" : \"false\" "
  "  },"
  " \"categories\"  : [ \"output\" ],"
  " \"defaults\"    : { \"sample.threads\": \"true\" }, "
  " \"options\"     : "
  " [ "
  "  { \"name\"        : \"sample.threads\","
  "    \"description\" : \"Sample all threads\","
  "    \"type\"        : \"bool\","
  "    \"services\"    : [ \"pthread\" ]"
  "  }"
  " ]"
  "}";

ConfigManager mgr;
mgr.add_config_spec(spec);

// Add a thread sampling channel using the spec and start recording
mgr.add("sampletracing(sample.threads=true,output=trace.cali)");
mgr.start();
// ...
mgr.flush();

If there was an error parsing the config spec, the error() method will return true and an error message can be retrieved with error_msg().

Config specification syntax

The config spec is a JSON dictionary with the following elements:

  • name: Name of the config spec.

  • description: A short one-line description. Included in the documentation string generated by get_documentation_for_spec().

  • services: List of Caliper services this config requires. Note that the config will only be available if all required services are present in Caliper.

  • config: A dictionary with Caliper configuration variables required for this config. Note that services will be added automatically based on the services entry.

  • categories: A list of option categories. Defines which options, in addition to the ones defined inside the config spec, apply to this config. The example above uses the “output” category, which makes the built-in output option for setting output file names available.

  • defaults: A dict with default values for any of the config’s options. Options not listed here default to empty/not set.

  • options: A list of custom options for this config.

void add_option_spec(const char *json)

Add a JSON option spec to this ConfigManager.

Allows one to define options for any config in a matching category. Option specifications must be added before querying or creating any configurations to be effective. If there was an error parsing the config spec, the error() method will return true and an error message can be retrieved with error_msg(). The following example adds a metric option to compute instructions counts using the papi service:

const char* spec =
  "{"
  " \"name\"        : \"count.instructions\","
  " \"category\"    : \"metric\","
  " \"description\" : \"Count total instructions\","
  " \"services\"    : [ \"papi\" ],"
  " \"config\"      : { \"CALI_PAPI_COUNTERS\": \"PAPI_TOT_INS\" },"
  " \"query\"       : "
  " ["
  "  { \"level\": \"local\", \"select\":"
  "   [ { \"expr\": \"sum(sum#papi.PAPI_TOT_INS)\" } ]"
  "  },"
  "  { \"level\": \"cross\", \"select\":"
  "   [ { \"expr\": \"avg(sum#sum#papi.PAPI_TOT_INS)\", \"as\": \"Avg instr./rank\" },"
  "     { \"expr\": \"max(sum#sum#papi.PAPI_TOT_INS)\", \"as\": \"Max instr./rank\" }"
  "   ]"
  "  }"
  " ]"
  "}";

ConfigManager mgr;
mgr.add_option_spec(spec);

//   Create a runtime-report channel using the count.instructions option
// and start recording.
mgr.add("runtime-report(count.instructions)");
mgr.start();

Option specification syntax

The option spec is a JSON dictionary with the following elements:

  • name: Name of the option.

  • category: The option’s category. The category defines which configs can use this option: An option is only available to configs which list this category in their “categories” setting.

  • description: A short one-line description. Included in the documentation string generated by get_documentation_for_spec().

  • services: List of Caliper services this option requires. Note that the option will only be available if all required services are present in Caliper.

  • config: A dictionary with Caliper configuration variables required for this option. Note that services will be added automatically based on the services entry.

  • query: Defines aggregation operations to compute performance metrics. Specific to “metric” options. There are two aggregation levels: local computes process-local metrics, and cross computes cross-process metrics in MPI programs. For each level, specify metrics using a list of “select” definitions, where expr defines an aggregation using a CalQL expression, and as provides a human-readable name for the metric. Metrics on the serial and local levels use runtime aggregation results from the “aggregate” service as input, metrics on the cross level use “local” metrics as input.

bool add(const char *config_string)

Parse the config_string configuration string and create the specified configuration channels.

Parses configuration strings of the following form:

<config> ( <option> = value, … ), …

e.g., “runtime-report,event-trace(output=trace.cali)”

If there was an error parsing the configuration string, the error() method will return true and an error message can be retrieved with error_msg().

If the configuration string was parsed successfully, ChannelController instances for the requested configurations will be created and can be accessed through get_all_channels() or get_channel(). The channels are initially inactive and must be activated explicitly with ConfigManager::start().

add() can be invoked multiple times.

In this add() version, key-value pairs in the config string that neither represent a valid configuration or configuration option will be marked as a parse error.

Returns:

false if there was a parse error, true otherwise

bool add(const char *config_string, argmap_t &extra_kv_pairs)

Parse the config_string configuration string and create the specified configuration channels.

Works similar to ConfigManager::add(const char*), but does not mark extra key-value pairs in the config string that do not represent a configuration name or option as errors, and instead returns them in extra_kv_pairs.

void load(const char *filename)

Load config and option specs from filename.

Loads JSON config and option specs from a file. The files can contain either a single config spec, a list of config specs, or a JSON object with both config and option specs in the following form:

{
 "configs": [
  { "name": "myconfig", ... }, ...
 ],
 "options": [
  { "name": "myoption", "category": ... }, ...
 ]
}

The schemas for config and option specs are described in ConfigManager::add_config_spec(const char*) and ConfigManager::add_option_spec(const char*), respectively.

If there was an error parsing the file, the error() method will return true and an error message can be retrieved with error_msg().

void set_default_parameter(const char *key, const char *value)

Pre-set parameter key to value for all configurations.

void set_default_parameter_for_config(const char *config, const char *key, const char *value)

Pre-set parameter key to value for config.

bool error() const

Returns true if there was an error parsing configuration strings.

std::string error_msg() const

Returns an error message if there was an error parsing configuration strings.

ChannelList parse(const char *config_string)

Parse config_string and return the specified configuration channels.

Unlike ConfigManager::add(const char*), this function does not add the specified configuration channels to the ConfigManager object’s internal list of channels.

If there was an error parsing the configuration string, the error() method will return true and an error message can be retrieved with error_msg().

Returns:

List of configuration channels

ChannelList get_all_channels() const

Return a list of channel controller instances for the requested configurations.

Returns:

An STL container with C++ shared_ptr objects to the ChannelController instances created from the configuration strings.

ChannelPtr get_channel(const char *name) const

Return a channel controller instance for configuration name.

Returns a C++ shared pointer containing the channel controller instance with the given name, or an empty shared_ptr object when no such channel exists.

void start()

Start all configured measurement channels, or re-start paused ones.

Invokes the ChannelController::start() method on all configuration channel controllers created by the ConfigManager. Equivalent to

ConfigManager mgr;
// ...
auto channels = mgr.get_all_channels();
for (auto& channel : channels)
    channel->start();

void stop()

Pause all configured measurement channels.

Invokes the ChannelController::stop() method on all configuration channel controllers created by the ConfigManager.

void flush()

Flush all configured measurement channels.

Invokes the ChannelController::flush() method on all configuration channel controllers created by the ConfigManager. Equivalent to

auto channels = mgr.get_all_channels();
for (auto& channel : channels)
    channel->flush();

std::string check(const char *config_string, bool allow_extra_kv_pairs = false) const

Check if the given config string is valid.

If allow_extra_kv_pairs is set to false, extra key-value pairs in the config string that do not represent configurations or parameters will be marked as errors.

Returns:

Error message, or empty string if input is valid.

std::vector<std::string> available_config_specs() const

Return names of available config specs.

Returns only the specifications whose requirements (e.g., available services) are met in this Caliper instance.

Returns:

Names of all available config specs for this ConfigManager.

std::string get_documentation_for_spec(const char *name) const

Return description and options for the given config spec.

Public Static Functions

static std::vector<std::string> available_configs()

Return names of global config specs.

Deprecated:

Query specific ConfigManager object instead.

static std::vector<std::string> get_config_docstrings()

Return descriptions for available global configs.

static std::string check_config_string(const char *config_string, bool allow_extra_kv_pairs = false)

Check if given config string is valid for global config specs. Deprecated.

If allow_extra_kv_pairs is set to false, extra key-value pairs in the config string that do not represent configurations or parameters will be marked as errors.

Deprecated:

Create a ConfigManager object and use its check() method.

Returns:

Error message, or empty string if input is valid.

struct ConfigInfo
#include <ConfigManager.h>

Define a config spec with custom ChannelController creation and option checking functions.

Public Members

const char *spec

JSON config spec.

CreateConfigFn create

Optional custom ChannelController creation function, or nullptr to use the default.

CheckArgsFn check_args

Optional argument checking function, or nullptr to use the default.

class Options
#include <ConfigManager.h>

Manages the list of options given to a ConfigManager config controller. Internal use.

Public Functions

bool is_set(const char *option) const

Indicates if option is in the options list.

bool is_enabled(const char *option) const

Indicates if option is enabled.

An option is enabled if it is present in the options list, and, for boolean options, set to true.

StringConverter get(const char *option, const char *default_value = "") const

Return the value for option, or default_value if it is not set in the options list.

std::string check() const

Perform a validity check.

std::vector<std::string> enabled_options() const

Return a list of all enabled boolean options.

void update_channel_config(config_map_t &config) const

Update the config controller’s Caliper configuration according to the requirements of the selected options.

Updates CALI_SERVICES_ENABLE and adds any additional configuration flags that may be required.

std::string build_query(const char *level, const std::map<std::string, std::string> &in, bool use_alias = true) const

Returns a CalQL query based on the fields in input and option list.

Construct a CalQL query for the option list. Example:

auto query = opts.build_query("cross", {
        { "select",   "sum(inclusive#sum#time.duration) as Total unit sec" },
        { "group by", "prop:nested" },
        { "format",   "tree" }
    });

Parameters:
  • level – The aggreatation level (“local” or “cross”)

  • in – Base CalQL clauses as needed by the controller

Returns:

Complete CalQL query statement

class RegionProfile : public cali::ChannelController
#include <RegionProfile.h>

Collect and return time profiles for annotated Caliper regions in a C++ map.

The RegionProfile class is a Caliper controller that allows one to collect and examine time spent in Caliper-annotated code regions within an instrumented program. It can compute inclusive or exclusive profiles. Start/stop profiling with the start() and stop() methods. Once started, time profiles can be retrieved at any time with exclusive_region_times() or inclusive_region_times().

Public Types

typedef std::tuple<std::map<std::string, double>, double, double> region_profile_t

A tuple containing the computed time profiles.

The first member is a string -> double STL map that stores the times per region. The map keys are the region names used in the annotations, e.g., “work” for CALI_MARK_BEGIN(“work”). Note that nested regions with the same name can’t be distinguished.

The second member stores the total time spent in the selected region type, and the third member stores the total time spent profiling.

Public Functions

RegionProfile()

Create a RegionProfile controller object.

Note that profiling must be started explicitly with the start() method.

region_profile_t exclusive_region_times(const std::string &region_type = "")

Return an exclusive time profile for annotated regions.

Exclusive time is the time spent in within a begin/end region itself, excluding time spent in sub-regions that are nested within.

Profiling must have been started with start().

By default, the result contains times for all region types with the CALI_ATTR_NESTED flag. Specifically, this includes regions marked with the Caliper annotations macros such as CALI_MARK_BEGIN. With the optional region_type argument, profiles can be calculated for a specific region type (Caliper attribute) only. In this case, the second value in the result tuple contains the total time spent in regions with the selected type.

As an example, the following code returns a profile for “function” regions:

RegionProfile rp;
rp.start();

// ...

std::map<std::string, double> function_times;
double total_function_time;
double total_profiling_time;

std::tie(function_times, total_function_time, total_profiling_time) = 
    rp.exclusive_region_times("function");

See also

region_profile_t

Returns:

A region_profile_t tuple with exclusive time per region in a region name -> time STL map, the total time for the selected region time, and the total time spent profiling. All time values are in seconds.

region_profile_t inclusive_region_times(const std::string &region_type = "")

Return an inclusive time profile for annotated regions.

Inclusive time is time spent within a begin/end region, including time spent in sub-regions that are nested within.

Other than returning inclusive rather than exclusive times, this method works the same as exclusive_region_times().

Returns:

A region_profile_t tuple with inclusive time per region in a region name -> time STL map, the total time for the selected region time, and the total time spent profiling. All time values are in seconds.

void clear()

Reset the profiling database.