Runtime Configuration

Overview

Specifying run-time configuration to simulations rather than requiring a full recompile improves iteration speed. Distribution of run-time configuration to Simulate processes consists of two steps:

  1. Receiving configuration values in the manager process through a mechanism similar to command-line parameters

  2. Making these parameters available to Simulate workers and global state processes as C++ data structures

Passing Options to the Manager

Parameters to simulations are defined in the user.cfg file found in the root folder of each demo. Currently two keys are defined.

  • user_bin_args_user_defined - user-defined arguments that may be passed to the simulation.

  • log_level - specifies the logging level that will be used by Simulate. Acceptable values are trace, debug, info, warn, error and fatal. Messages at the specified level or above will be logged.

A user.cfg for a demo might look like:

user_bin_args_user_defined = "--elasticity 10 --population-density 12"
log_level = "info"

Simulate is not responsible for the parsing of user-defined arguments so alternative arguments formats are possible:

user_bin_args_user_defined = "SCENE=tower ELASTICITY=10"

Parsing Arguments in the Manager

Accessing user-defined arguments in the manager can be done after initialisation of the process. A call to argument_parse is used to process the contents of argv (which should not be accessed directly) into the aether::arguments type.

int main(int argc, char *argv[]) {
    // Initialization of Hadean libraries and logging
    hadean::init();
    const char *process_name = "AE_Manager";
    prctl(PR_SET_NAME, process_name);
    aether::log::init(process_name, static_cast<uint64_t>(hadean::get_pid()));
    AETHER_LOG(INFO)("Initialisation complete");
    // Parse arguments supplied to this process
    aether::arguments arguments;
    arguments.workers = 96;
    // Set other default arguments here 
    argument_parse(argc, argv, &arguments);
    aether::log::set_level(arguments.log_level);

    // Access the user-defined arguments
    const std::vector<std::string> user_args = arguments.user_args;

Passing Configuration Options to Other Aether Processes

Information must be encoded as a C++ data type to pass run-time information to Simulate workers and the global state. This type must be serializable using Simulate's serialization framework. Using a trivially copyable type to carry configuration data removes the need for writing serialization code.

#include <aether/common/serde_derive.hh>
// Contains the run-time configuration
struct demo_parameters {
   double elasticity;
   size_t world_size;
};
// Derive serializer and deserializer for trivially copyable type
SERDE_DERIVE_TRIVIAL(demo_config);

Passing it to the build_entity_simulation_manager function after the first two parameters, provides the argument to Simulate workers. Any number of additional parameters can be provided, and will be forwarded to the constructor of the user-defined state class (user_cell_state_impl in this example). Note that the first argument to the constructor of the user-defined state class will be an instance of aether::cell_state. Similarly, parameters can also be forwarded to the constructor of the global state process (example_global_state in this example):

const demo_parameters params = args_to_params(arguments.user_args);
    auto static_args = arguments.to_octree_params<octree_traits>();
    // The global state will be constructed with a call to
    // example_global_state(const demo_parameters&)
    static_args.configure_global_state<example_global_state>(params);
    // The manager will be constructed with a call to 
    // user_cell_state_impl(const aether_cell_state&, const demo_parameters&)
    auto manager = aether::build_entity_simulation_manager<user_cell_state_impl>(
            arguments.workers, static_args, params
    );

Hadean Simulate feature flags

Simulate has a number of flags which can be used to enable and disable various simulation behaviours. Although the flags are run-time configurable, they remain static for the duration of the simulation. The values can be set in the static arguments structure which is passed as a parameter to construct the simulation manager.

auto static_args = arguments.to_octree_params<octree_traits>();
static_args.feature_flags = FAST_MODE | PHASE_BARRIERS;
auto manager = aether::build_entity_simulation_manager<user_cell_state_impl>(arguments.workers, static_args, ua);

The full list of available flags can be found in aether/feature_flags.hh. We document the most important ones here:

  • FAST_MODE. Enable a number of options that benefit simulation performance. We recommend that customers always use this option, since leaving it off will degrade simulation performance and only has benefit for Hadean's internal Simulate development.

  • PHASE_BARRIERS. Enables barrier operations between each of Simulate's phases. This may incur some performance degradation, but enables time to be more accurately attributed to phase times collected using the metrics functionality.

  • DISABLE_MERGE - If this flag is set, Simulate will make a best-effort attempt to avoid merging cells. This should only be set if the simulation use-case requires it, since it will negatively impact Simulate's ability to load balance.

  • DISABLE_SPLIT - If this flag is set, Simulate will make a best-effort attempt to avoid splitting cells. This should only be set if the simulation use-case requires it, since it will negatively impact Simulate's ability to load balance.

See also the feature flags governing asynchronous cell initialisation here.

Last updated