Skip to content

Configuration

Overview

Configuration files of Optimizer Studio are located in the installation directory /opt/concertio-optimizer/studio/. You can specify your own configuration files via command line switches.
There are two configuration files:

  1. knobs.yaml - Specifies the knobs, input metrics and target function of Optimizer Studio.
  2. settings.yaml - Specifies the system-wide settings of Optimizer Studio.

Optimization Target

Users can configure Optimizer Studio to search for the optimal parameters that maximize a specific target metric.

The target metric can be one of the following:

  1. performance - defined as the total number of retired instructions msr.inst_retired_all measured in all CPUs per second.
  2. energy - defined as the package energy of the CPUs per retired instruction. In case of energy, Optimizer Studio will attempt to minimize the energy per retired instruction.
  3. duration - optimizes for the total duration of a workload, running it until completion and changing knob values between runs.
  4. Any other available metric, as long as it is sampled by Optimizer Studio, such as proc.diskstats.sda.sectors_written. See below more details about metrics.

Example
In order to define performance as a target metric, define the following in the knobs.yaml file (more details about knobs.yaml below)

domain:
  common:
    target: performance

knobs.yaml: knob definition

Knobs are tunable parameters of the system which Optimizer Studio will try to change in order to optimize the system.

Concertio Optimizer Studio ships with embedded set of knob definitions containing many knobs that were tested and benchmarked by Concertio engineers. If you want to use these knobs, specify --knobs=embedded command line switch.

It is possible to provide additional knob files by using the --knobs=/path/to/knob-file.yaml command line switch, where you can add custom knobs that are relevant for your system. If you don't supply your knobs file, the embedded knobs will be used automatically.

Optimizer Studio can accept any number of --knobs=PATH command line switches. In such case Optimizer Studio loads knob files in the order they appear in the command line. This way a knob files appearing later can overload any settings in previous knob files. Note that this doesn't include embedded knobs which are always processed first.

knobs section: adding a Knob

It is possible to add or override an existing knob by adding a knob section to the knobs list. Each knob section contains a few values and POSIX shell scripts used for defining and manipulating the knob.

Knob types

Optimizer Studio can work with two kinds of knobs - scripted knobs and memory knobs.
The main differences between two knob types are as follows:

  1. scripted knobs use two scripts which are used to get and set knob values to the system:

    • get_script to return current knob value
    • set_script to set new knob value
  2. The current values of memory knobs are passed to the workload script as environment variables on each workload invocation. For example, $my_knob. Such knobs can't affect the system in any other way

  3. The knob baseline value for a scripted knob is obtained by get_script at the beginning of the optimization. For memory knobs the first value of the options list (below) is used for this purpose
  4. Since shell environment variables can consist only of letters, digits or underscore characters, this limitations are applied to the names of memory knobs as well

Knob scripts

  1. get_script - returns current knob value. Mandatory for scripted knobs
  2. set_script - sets new knob value. Mandatory for scripted knobs
  3. pre_set_script - when provided, this script is run prior to running any of the set_script(s)
    Note that in case more than one knob refers to the same pre_set_script, identical script invocations will be merged.
  4. post_set_script - when provided, this script is run after running any of the set_script(s)
    Note that in case more than one knob refers to the same post_set_script, identical script invocations will be merged.
  5. enable_script - when provided, returns 1/0 to indicate whether the knob can be enabled or should be discarded. When not provided, the knob is enabled by default.
  6. options_script - when provided, populates available knob options. When not provided, available options must be provided by options list (below).
  7. devices_script - when provided, returns list of applicable devices, and the knob is split into multiple per-device knobs, e.g.
    io.scheduler → io.scheduler.sda, io.scheduler.sdb, io.scheduler.sdc

Each knob script is allowed to use the following environment variables:

  1. $KNOB_VAL - knob value being set by set_script
  2. $KNOB_DEV - device name, in device-specific knobs, as returned by devices_script

Optional knob parameters

  1. options - a list of available knob options
  2. disable - when provided, the knob will be discarded and erased from internal data structures. This parameter overrides enable_script (above).
  3. skip_tuning - when provided, the knob will be excluded from the tuning process

Knob options definition

A simplest way to define knob options is to list all valid values explicitly:

options:
  values: [10, 15, 20]

The second way is to define an options script which returns the list of option values. For example, the following script creates a list of numbers from 0 to 7 for a computer with 8 logical CPUs

options:
  script: cat /proc/cpuinfo | awk '/processor/ {print $3}'

Yet another possibility is to define a list of options using numeric range:

options:
  range:
    min: 1
    max: 16
    step: 1
    format: --num-threads=%d

This definition creates a list of options "--num-threads=1", --num-threads=2, etc.
Printf style format field is optional. It contains a string with one of supported format specifiers, like in the example:

Format Numeric Value Knob Value
"-O%d" 2 -O2
"--pi=%.2f" 3.14159 --pi=3.14
"--pi=%.2f" 3 --pi=3.00
"%g" 5000000 5000000
"%g" 2.718000 2.718

You can combine different ways of specification:

options:
  values: [ "" ]
  range:
    min: 1
    max: 16
    step: 1
    format: --num-threads=%d

The example above adds an empty option value in addition to the ones defined by the range.

Disabling a knob

It is possible to disable a knob, either temporarily or permanently, without actually removing its definition from the knobs file.
To temporarily disable a knob, add to the knob section the following value:

skip_tuning: ""

To permanently erase a knob from the internal data structures, either add to the knob section the following value:

disable: ""

or define an appropriate enable_script:

enable_script: "echo -n 0"

Note that this approach allows disabling embedded knobs as well.

scripts section: named reusable scripts

Frequently different knobs reuse the same scripts, in particular pre_set_script(s)/post_set_script(s), as these are intended to preface/conclude multiple knobs.
In the scripts section, reusable scripts are represented as name:code pairs. Instead of providing the full code, it is possible to refer the script name prefixed with a @ symbol, e.g. "@my-script".

Examples

A: vm.dirty_background_ratio

domain:
  common:
    knobs:
      sys.vm.dirty_background_ratio:
        description: "The number of pages at which the pdflush threads begin writeback of dirty data."
        get_script: "/sbin/sysctl -n vm.dirty_background_ratio"
        set_script: "/sbin/sysctl -w vm.dirty_background_ratio=$KNOB_VAL"
        options: [10, 15, 20]

B: io.scheduler

Below is a more complex knob example of a device-specific knob. Eventually, this knob definition produces multiple knobs: io.scheduler.sda, io.scheduler.sdb etc.

domain:
  common:
    knobs:
      io.scheduler:
        description: "Block device scheduling algorithm selector."
        get_script: "cat /sys/block/$KNOB_DEV/queue/scheduler | sed 's/.*\\[\\([^]]*\\)\\].*/\\1/g'"
        set_script: "echo $KNOB_VAL > /sys/block/$KNOB_DEV/queue/scheduler"
        device_script: "ls -d /sys/block/sd* | cut -d/ -f 4"
        options_script: cat /sys/block/$KNOB_DEV/queue/scheduler | sed 's/\[\|\]//g ; s/ $//g ; s/\s/\n/g'

Passing knob values to the workload

The easiest way of passing knob values to applications is via the shell environment using memory knobs. Below is an example of a simple knob with five values:

domain:
  common:
    knobs:
      my_knob:
        options: [1,2,3,4,5]

Note that no set_script or get_script are defined for memory knobs. The workload scripts will receive $my_knob as an environment variable, as follows:

#!/bin/bash
executable_name ${my_knob}

In the above case, the baseline value of my_knob is 1 as it is the first value in the options list.

It is also possible to use scripted knobs to pass values of application knobs. One way to achieve this is using the filesystem. For example, a knob's set script can write a value into /tmp/knob_file:

domain:
  common:
    knobs:
      my_knob:
        get_script: "cat /tmp/knob_file"
        set_script: "echo $KNOB_VAL > /tmp/knob_file"
        options: [1,2,3,4,5]

Then, the workload script can read this value when invoked. For example:

#!/bin/bash
my_parameter=$(cat /tmp/knob_value)
executable_name ${my_parameter}

In order for the above to work, the file /tmp/knob_file should be populated, for example by:

$ echo "1" > /tmp/knob_file

The workload script can also read the knob names and values through an associated array. This is useful when experimenting with numerous knobs in the configuration files because the workload script can detect which knobs have been defined. Below is an example:

# source studio functions
. /opt/concertio-optimizer/studio/studio-functions.bash
# call memory knobs associative array function
get_memory_knobs_assoc
for K in "${!ASSOC_KNOBS_ARRAY[@]}"; do
        args+="--$K=${ASSOC_KNOBS_ARRAY[$K]} "
done
executable_name $args

The code in knobs.yaml can be tested as follows:

$ optimizer-studio --knobs=knobs.yaml --testknob=my_knob
++
I[3857][03:34:41.278] Concertio Optimizer, version 1.3
I[3857][03:34:41.278] License information: EVALUATION (not intended for on-going commercial use) valid until: June 16, 2018
I[3857][03:34:41.285] Knob my_knob: set value: 1 --> 2 
I[3857][03:34:41.287] Knob my_knob: set value: 2 --> 3 
I[3857][03:34:41.288] Knob my_knob: set value: 3 --> 4 
I[3857][03:34:41.290] Knob my_knob: set value: 4 --> 5 
I[3857][03:34:41.292] Knob my_knob: set value: 5 --> 1 [baseline]
E[3857][03:34:41.293] Knob my_knob test: success
--

metrics section: named HW and SW metrics

Metrics are used by Optimizer Studio to learn about the system behavior and to detect different phases of execution. Optimizer Studio will then attempt to find an optimal knob configuration that maximizes a certain sampled metric for each phase. The metrics are sampled periodically.

Metrics definition

Comma separated regular expressions define which metrics are sampled, and which metrics are excluded.

domain:
  common:
    include_metrics: [msr.*, proc.*]
    exclude_metrics: [proc.diskstats.sda.sectors_written]

In the above example, all msr metrics and all proc metrics, except for proc.diskstats.sda.sectors_written will be considered by Optimizer Studio for learning about the system behavior.

User-defined metrics

Optimizer Studio supports user-developed plugins for sampling custom metrics.

Target metric

You can designate one of the metrics to be used as a target one. Optimizer Studio will search for the optimal parameters that maximize the target metric.

domain:
  common:
    target: performance

You can also direct the Optimizer Studio to minimize the target metric, like below.

domain:
  common:
    target: my.custom.metric:min

max keyword can be used as well to explicitly specify the optimization goal.

Importing Configuration Files

It is possible to import configuration files by using the import directive. For example, the default embedded knobs of Optimizer Studio can be imported as follows:

import:
  optimizer.studio:
domain:
  common:
    knobs:
...

Other embedded knob definitions will always have the optimizer. prefix. In order to import a configuration file from the filesystem, its yaml extension should be removed and slashes (/) need to be converted into dots .. For example, my_configurations/my_software_knobs.yaml will be imported as my_configurations.my_software_knobs.

Filtering knobs from imported files

Specific knobs can be selected from imported files using regular expressions. In the following example, all embedded knobs are imported, except those that have "net" in their names:

import:
  optimizer.studio:
    include_knobs: [ .* ]
    exclude_knobs: [ .*net.* ]

File-specific directives

Configuration files can have their own enable and onload directives, as shown in the following example:

import:
  my_example_import:
enable:
  script: echo 1
onload:
  source: my_script.sh
domain: ...

File-specific enable

The enable directive determines whether the configuration file should be loaded. It can either be a scalar value (enable:), a script, or a sourced script. A script can be defined as following:

enable:
  script: echo 1

A sourced script can be defined as follows:

enable:
  source: my_filesystem_script.sh

In all of these cases, if 1 is returned, the configuration file is loaded. Otherwise it is skipped.

Passing arguments to the enable scripts of imported files

Passing arguments as environment variables is possible using the args directive:

import:
  my_example_import:
    args:
      MY_ENV_VARIABLE: value

The parameter can then be used in my_example_import.yaml's enable script as follows:

enable:
  script: echo ${MY_ENV_VARIABLE}

File-specific onload

When a configuration file is found to be enabled, the onload script is invoked. It can either be sourced (using source:) or in-lined (using script:).

Workload definition and multi-objective optimization

Workloads can be defined in a single script, or can have a more complex definition in the configuration files. A complex workload can be defined as a sequence of steps, each comprising a script, metrics and validity checks, as following:

  1. Script: A script that runs the workload step
  2. Metrics: After the script (if defined) runs, metrics are gathered from the filesystem
  3. Validity checks: After metrics are gathered, they are validated in a sequence of tests. If all checks pass, the next workload step is executed. Otherwise, the knob configuration is deemed invalid and Optimizer Studio resumes testing a different configuration.

After all the steps are executed and validated, a target metric is calculated. Multiple objectives can be specified through scalarization in the target metric.

For example:

workload_settings:
  workloads:
    - 
      script: ./my_workload_1.sh my_arg1
      metrics: 
        workload1_output: /tmp/my_target1
        my_metric1: /tmp/my_metric1
      validity: 
        - workload1_output > 3200
        - my_metric1 < 200  
    - 
      script: ./my_workload_2.sh my_arg2
      metrics:
        workload2_output: /tmp/my_target2
      validity: workload2_output < 10000
  target: workload1_output * 0.12 + workload2_output * 8 - my_metric1

In the above example, Optimizer Studio will come up with a configuration to test. It will then run ./my_workload_1.sh my_arg1. When done, it will check whether the contents of /tmp/my_target1 is higher than 3200, and whether the contents of /tmp/my_metric is lower than 200. If both checks pass, Optimizer Studio will proceed to running the next script in the sequence. Otherwise, Optimizer Studio will come up with a different configuration and start testing the first workload in the sequence.

If all the workloads run correctly and their validity tests pass, Optimizer Studio will calculate the target according to the formula at the last line of the example, and report it as the target metric of that configuration.

System-wide Settings

System-wide settings can be configured in the settings.yaml file or directly in the configuration file, as follows:

global_settings:
  max_option_cv: 0.02

Note that some settings need to be defined in settings.yaml or an equivalent parameters file, such as out_directory, metrics_csv_directory, and shell_command. All of the others can be defined in the regular configuration files, together with the knobs. It is recommended to use the template in the installation directory.

The possible settings are summarized below:

Setting name Default value Description
save_interval_minutes 60 The interval in minutes between saving the data file to the disk.
min_samples_per_option 1 The minimum number of samples per option. This is used in conjunction with max_option_cv.
max_option_cv 0.04 The maximum allowed coefficient of variation of the mean of the measurements per option. A high value will mandate additional measurements.
min_baseline_samples 2 The minimum number of samples per option. This is used in conjunction with max_baseline_cv.
max_baseline_cv 0.04 The maximum allowed coefficient of variation of the mean of the measurements in baseline settings. A high value will mandate additional measurements.
out_directory ${HOME}/.concertio Concertio Optimizer Studio generates output data such as optimization database file, log files, etc. into this location.
metrics_csv_filename - If specified, Optimizer Studio creates a CSV file with the details of all the knob settings and metric measurements.
interval_seconds 1 The interval in seconds between samples. Relevant only for asynchronous sampling mode.
max_invalid_samples_per_option 0 The maximum allowed invalid measurements per option, above which the configuration is considered invalid and will not be further tested.
shell_command (experimental) /bin/sh +e This defines the backend shell of the knobs and metrics. It is possible to run all knobs and metrics scripts on remote hosts using a different shell command. This setting is experimental and will most probably move to another location in one of the nearby releases.
optimization_strategy evolution The algorithm employed for searching through the knobs. Available options are greedy and evolution.
optimization_strategy_settings Settings specific for each optimization strategy. Only settings specific for the selected strategy will be parsed.