Statistics API

Introduction

Beginning with version 5.0 of SST, a common interface statistics API was developed for for SST components.

The goal of the statistics API was to create a consistent method for collecting statistic data across all SST components, using a simplified interface. Additionally, the API is designed to allow growth in the architecture with minimal impact to users of the API.

An example of statistic usage can be examined in the simpleElementExample under <sstroot>/sst/elements.

General Operation

User’s Tasks

  1. The user identifies the statistics they wish to collect and assign names to them (these names are generic and not tied to any specific collection type i.e. histogram, accumulator, etc).
  2. The user adds all statistic names to the component’s ElementInfoStatistic structure. The ElementInfoStatistic identifies the Statistic Name, description and an enable level for the statistic. The ElementInfoStatistic must also be tied to the components ElementInfoComponent.
  3. In the component (during construction), each statistic name is registered along with its collection data type. The registration method will instantiate a statistic object in the system and return a pointer to the registered statistic. If the statistic is not enabled (see below), a pointer to a NullStatistic will be returned which will allow all statistic API calls to work, but collects no data.
  4. The supported collection data types are:
    • uint32_t
    • uint64_t
    • int32_t
    • int64_t
    • float
    • double
  5. The component will call registeredStatistic->addData(data) to add data to the statistic.
  6. The user will modify the simulation’s python input file to identify the type of Statistic Output desired, and enable the statistics. Enabling the statistic also allows the user to set the desired collection type (histogram, accumulator) for that statistic name. For more information on the syntax of the Python file see Python File Format.

Note On registering Statistics: All statistics must be registered during component construction before simulation start (sim time advances). After simulation start, attempting to register statistics will cause a run-time error except under the following condition: Attempting to register a statistic with the same “signature” as a previously (before simulation start) registered statistic will return a pointer to the previously registered statistic. This allows components to be destroyed at runtime (the component must not delete the statistic object) and if constructed again to re-register previously registered statistics.

Example C++ Code

static const ElementInfoStatistic StatisticsComponent_statistics[] = {
    { "statA", "Statistic A - Collecting U32 Data", "reads", 1},   // Name, Desc, Units, Enable Level 
    { "statB", "Statistic B - Collecting U64 Data", "writes",  2}, 
    { "statC", "Statistic C - Collecting float Data", "%done", 3}, 
    { NULL, NULL, NULL, 0 }
};

static const ElementInfoComponent testComponent[] = {
    { "StatisticsComponent",            // Name
      "StatisticsComponent Desc",       // Description
      NULL,                             // PrintHelp
      create_ StatisticsComponent,      // Allocator
      StatisticsComponent_params,       // Parameters
      StatisticsComponent_ports,        // Ports
      COMPONENT_CATEGORY_UNCATEGORIZED, // Category
      StatisticsComponent_statistics    // Statistics    
    },
    { NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL}
};

//////

Statistic<uint32_t>*  statisticA;
Statistic<uint64_t>*  statisticB;
Statistic<float>*     statisticC;

statisticA = registerStatistic<uint32_t>("statA");
statisticB = registerStatistic<uint64_t>("statB");
statisticC = registerStatistic<float>("statC");

statisticA->addData(data_U32);
statisticB->addData(data_U64);
statisticC->addData(float_data);

Example Python Code

sst.setStatisticLoadLevel(7)
sst.setStatisticOutput("sst.statOutputCSV", {"filepath" : "./TestOutput.csv",
                                             "separator" : ", " } )

compA = sst.Component("statA", "Element.StatisticsComponent")
compB = sst.Component("statB", "Element.StatisticsComponent")
compC = sst.Component("statC", "Element.StatisticsComponent")

sst.enableAllStatisticsForComponentType("Element.StatisticsComponent", 
                                       {"type":"sst.HistogramStatistic",
                                        "minvalue" : "10",
                                        "binwidth" : "10", 
                                        "numbins"  : "41", 
                                        "IncludeOutOfBounds" : "1",
                                        "rate" : "100 ns",
                                        "startat" : "100 ns",
                                        "stopat" : "900 ns"})

Operation During Simulation

  1. At the start of simulation, the selected Statistic Output will be instantiated, and the Statistic Load Level identified.
  2. When the statistic is registered by a call to component::registerStatistic(), a number of checks to see if the statistic can be enabled are performed:
    1. Verify that the Statistic Name is found in the ElementInfoStatistic.
    2. Verify that the statistic has be enabled in the Python File.
    3. Perform validity checks on the parameters passed from the Python statistic enable function.
    4. Verity that the system statistic’s load level > statistic enable level defined in the ElementInfoStatistic
    5. Verity that the Statistic Name (with statSubId) is unique.
  3. if the checks during component::registerStatistic() succeed, the system will instantiate a Statistic object identified by the type parameter. Otherwise, a NullStatistic will be returned.
  4. During the simulation, a component can call registeredStatistic->addData(data). This will add the data to the appropriate statistic collection type object instantiated during simulation startup.
  5. During simulation, the statistic can be setup to output its data at a periodic rate or by number of addData() events.
    • The statistic can be optionally configured to clean its data on every output.
    • The statistic collection ability can optionally be disabled permanently or for a duration of time.
    • The statistic periodic output can optionally be delayed for a duration of time.
  6. During simulation, the statistic can be setup to start and/or stop at a given point in time.
  7. At the end of the simulation, any information generated by the Statistic Output can be analyzed.

Notes on Sub-Components

  1. Statistics can be registered in subcomponents.
  2. The ElementInfoSubComponent “stats” field must be populated similarly to how a ElementInfoComponent is setup (see examples above).
  3. In the Python script, when enabling a statistic for a subcomponent, the parent component that instantiated the subcomponent must be used as the component name or component type.

Statistics API

Statistic and StatisticBase

Components and SubComponents

template <typename T>
Statistic<T>* registerStatistic(std::string statName, std::string statSubId = "")

Statistic Collection Types

Statistic Collection Types are templated classes derived from Statistic<T>.

The available Collection types are:

When instantiated, Statistics will register data fields with the Statistic Output. Fields may be optionally registered depending upon the parameters provided (from the Python file) when the statistic is instantiated.

Duplicated registered fields are not unique across statistics. The allows for common field names to be used thereby reducing output sizes.

When an Statistic is commanded to perform an output, the Statistic will update all registered data fields to the Statistic Output.

When output, the registered fields will include an indicator of the data type for that field

Adding Additional Collection Types To The Core can be achieved by implementing the new statistic collection type in the sst/core/statapi/<collectiontype>.h, and then adding the new type in simulation::CreateStatistic(). Reference existing

sst.AccumulatorStatistic

Parameter startat (default = 0ns) will identify a time in the simulation when to enable the statistic. If set to non-zero, the statistic will not be enabled at startup. Parameter stopat (default = 0ns) will identify a time in the simulation when to disable the statistic. If set to zero, the statistic will not be disabled.

sst.HistogramStatistic

sst.UniqueCountStatistic

sst.NullStatistic

Statistic Outputs

Statistic Outputs control how the output is generated

The available outputs are:

Duplicated registered fields are not unique across statistics. The allows for common field names to be used thereby reducing output sizes.

Adding Additional Statistic Outputs To The Core can be achieved by implementing the new statistic output in the sst/core/statapi/<statoutput>.h/.cc, and then adding the new type in factory::LoadCoreModule_StatisticOutputs()

sst.statOutputConsole

sst.statOutputTXT

sst.statOutputCSV

sst.statOutputTXTgz

sst.statOutputCSVgz

Custom Statistic Outputs

Custom statistic outputs can be created within an element if the core provided outputs do not meet the users needs.

The custom statistic output must be derived from the StatisticOutput class (which is itself derived from the Module class).

To instantiate the custom statistic output, use the sst.setStatisticOutput() method in the Python input file.

sst.setStatisticOutput("myElementExample.myStatisticOutput", {"filepath" : "./TestOutput.xyx"})              

For examples of Statistic Outputs, look at: