Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions engine/report/json/report_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,19 @@ void profileset_json2( const profileset::profilesets_t& profileset, const sim_t&

obj[ "iterations" ] = as<uint64_t>( result.iterations() );

if ( sim.profileset_cull.enabled )
{
if ( profileset->culled() )
{
obj[ "culled" ] = true;
obj[ "culled_reason" ] = profileset->culled_reason();
obj[ "culled_iterations" ] = profileset->culled_iterations();
obj[ "culled_mean" ] = profileset->culled_mean();
obj[ "culled_error" ] = profileset->culled_error();
obj[ "culled_error_type" ] = profileset->culled_error_type_cstr();
}
}

if ( profileset->results() > 1 )
{
auto results2 = obj[ "additional_metrics" ].make_array();
Expand Down Expand Up @@ -1068,6 +1081,20 @@ void profileset_json3( const profileset::profilesets_t& profilesets, const sim_t
obj[ "name" ] = profileset->name();
auto results_obj = obj[ "metrics" ].make_array();

// Profileset culling metadata at profileset level
if ( sim.profileset_cull.enabled )
{
if ( profileset->culled() )
{
obj[ "culled" ] = true;
obj[ "culled_reason" ] = profileset->culled_reason();
obj[ "culled_iterations" ] = profileset->culled_iterations();
obj[ "culled_mean" ] = profileset->culled_mean();
obj[ "culled_error" ] = profileset->culled_error();
obj[ "culled_error_type" ] = profileset->culled_error_type_cstr();
}
}

for ( size_t midx = 0; midx < sim.profileset_metric.size(); ++midx )
{
const auto& result = profileset->result( sim.profileset_metric[ midx ] );
Expand Down Expand Up @@ -1231,6 +1258,19 @@ void to_json( const ::report::json::report_configuration_t& report_configuration
options_root[ "profileset_metric" ] = util::scale_metric_type_abbrev( sim.profileset_metric.front() );
options_root[ "profileset_multiactor_base_name" ] = sim.profileset_multiactor_base_name;

if ( sim.profileset_cull.enabled )
{
auto cull = options_root[ "profileset_cull" ];
cull[ "enabled" ] = true;
cull[ "method" ] = sim.profileset_cull.method_name();
cull[ "min_iterations" ] = sim.profileset_cull.min_iterations;
if ( sim.profileset_cull.uses_alpha() )
cull[ "alpha" ] = sim.profileset_cull.alpha;
else
cull[ "margin" ] = sim.profileset_cull.margin;
cull[ "metric" ] = util::scale_metric_type_abbrev( sim.profileset_cull.metric );
}

to_json( options_root[ "dbc" ], *sim.dbc );

if ( sim.scaling->calculate_scale_factors )
Expand Down Expand Up @@ -1308,6 +1348,26 @@ void to_json( const ::report::json::report_configuration_t& report_configuration
add_non_zero( stats_root, "total_heal", sim.total_heal );
add_non_zero( stats_root, "total_absorb", sim.total_absorb );

if ( sim.profileset_cull.enabled )
{
const std::string best_name = sim.profileset_cull.best_name.empty()
? sim.profileset_multiactor_base_name
: sim.profileset_cull.best_name;

auto cull_stats = stats_root[ "profileset_cull" ];
cull_stats[ "method" ] = sim.profileset_cull.method_name();
cull_stats[ "metric" ] = util::scale_metric_type_abbrev( sim.profileset_cull.metric );

add_non_zero( cull_stats, "best_name", best_name );

if ( sim.profileset_cull.baseline_seeded )
{
cull_stats[ "best_error" ] = sim.profileset_cull.best_error;
cull_stats[ "best_iterations" ] = sim.profileset_cull.best_iterations;
cull_stats[ "best_mean" ] = sim.profileset_cull.best_mean;
}
}

if ( sim.report_details != 0 )
{
// Targets
Expand Down
42 changes: 42 additions & 0 deletions engine/report/report_html_sim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,48 @@ void print_profilesets( std::ostream& out, const profileset::profilesets_t& prof

print_profilesets_chart( out, sim );

// Profileset culling indicator and culled list (moved below charts)
if ( sim.profileset_cull.enabled )
{
out << "<h3 class=\"toggle\">Profileset culling details</h3>\n";
out << "<div class=\"toggle-content hide\">\n";

out << "<div class=\"note\" style=\"margin:6px 0;\">";
out << "Profileset culling enabled: method="
<< sim.profileset_cull.method_name()
<< ", min_iters=" << sim.profileset_cull.min_iterations;
if ( sim.profileset_cull.uses_alpha() )
out << ", alpha=" << sim.profileset_cull.alpha;
else
out << ", margin=" << sim.profileset_cull.margin;
out << "</div>\n";

// List culled profiles if any
bool any_culled = false;
for ( const auto& pset : profilesets.profilesets() )
{
if ( pset->culled() ) { any_culled = true; break; }
}
if ( any_culled )
{
out << "<div class=\"note\" style=\"margin:6px 0;\"><strong>Culled profiles:</strong><ul>";
for ( const auto& pset : profilesets.profilesets() )
{
if ( !pset->culled() ) continue;
out << "<li>" << util::encode_html( pset->name() )
<< ": " << util::encode_html( pset->culled_reason() )
<< " (iters=" << pset->culled_iterations()
<< ", mean=" << util::round( pset->culled_mean(), 2 )
<< ", error=" << util::round( pset->culled_error(), 4 )
<< ", type=" << pset->culled_error_type_cstr() << ")";
out << "</li>";
}
out << "</ul></div>\n";
}

out << "</div>\n"; // end toggle-content
}

out << "</div>";
out << "</div>";
}
Expand Down
4 changes: 4 additions & 0 deletions engine/sc_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ int sim_t::main( const std::vector<std::string>& args )
plot->analyze();
reforge_plot->analyze();

if ( profileset_cull.enabled ) {
seed_profileset_cull_from_baseline();
}

if ( canceled == 0 && !profilesets->iterate( this ) )
canceled = true;
else
Expand Down
22 changes: 22 additions & 0 deletions engine/sim/profileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void simulate_profileset( sim_t* parent, profileset::profile_set_t& set, sim_t*&
// Reset random seed for the profileset sims
profile_sim -> seed = 0;
profile_sim -> profileset_enabled = true;
profile_sim -> profileset_current_name = set.name();
profile_sim -> report_details = 0;
if ( parent -> profileset_work_threads > 0 )
{
Expand Down Expand Up @@ -156,6 +157,22 @@ void simulate_profileset( sim_t* parent, profileset::profile_set_t& set, sim_t*&
.stddev( data.std_dev )
.mean_stddev( data.mean_std_dev )
.iterations( progress.current_iterations );

// If culled, persist snapshot information for JSON/HTML reporting on primary metric only
if ( profile_sim->culled && metric == parent->profileset_metric.front() )
{
// error to record depends on method: CI mode wants half-width, t-test wants SE
auto etype = ( parent->profileset_cull.prefers_standard_error() ) ?
profileset::profile_set_t::cull_error_type_e::STANDARD_ERROR :
profileset::profile_set_t::cull_error_type_e::CI_HALF_WIDTH;
double err_val = parent->profileset_cull.select_error(data.mean_std_dev * parent->confidence_estimator, data.mean_std_dev / sqrt(parent->iterations) );
set.set_culled( true,
profile_sim->culled_reason,
progress.current_iterations,
data.mean,
err_val,
etype );
}
} );

if ( ! parent -> profileset_output_data.empty() )
Expand All @@ -174,6 +191,11 @@ void simulate_profileset( sim_t* parent, profileset::profile_set_t& set, sim_t*&
parent -> event_mgr.total_events_processed += profile_sim -> event_mgr.total_events_processed;

set.cleanup_options();

if ( profile_sim->culled )
{
fmt::print( stderr, "\nProfileset '{}' culled: {}\n", set.name(), profile_sim->culled_reason );
}
}

// Figure out if the option defines new actor(s) with their own scope
Expand Down
42 changes: 42 additions & 0 deletions engine/sim/profileset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,19 @@ class profile_set_t
std::vector<profile_result_t> m_results;
std::unique_ptr<profile_output_data_t> m_output_data;

// Culled metadata (set when profileset culling terminates a run early)
bool m_culled = false;
std::string m_culled_reason;
uint64_t m_culled_iterations = 0;
double m_culled_mean = 0.0;
double m_culled_error = 0.0;
// CI half-width or standard error depending on cull method

public:
enum class cull_error_type_e { NONE = 0, CI_HALF_WIDTH, STANDARD_ERROR };
private:
cull_error_type_e m_culled_error_type = cull_error_type_e::NONE;

public:
profile_set_t( std::string name, sim_control_t* opts, bool has_output );

Expand Down Expand Up @@ -415,6 +428,35 @@ class profile_set_t

return *m_output_data;
}

// Culled metadata accessors
bool culled() const { return m_culled; }
const std::string& culled_reason() const { return m_culled_reason; }
uint64_t culled_iterations() const { return m_culled_iterations; }
double culled_mean() const { return m_culled_mean; }
double culled_error() const { return m_culled_error; }
profile_set_t::cull_error_type_e culled_error_type() const { return m_culled_error_type; }
const char* culled_error_type_cstr() const {
switch ( m_culled_error_type ) {
case profile_set_t::cull_error_type_e::CI_HALF_WIDTH: return "ci_half_width";
case profile_set_t::cull_error_type_e::STANDARD_ERROR: return "standard_error";
default: return "none";
}
}
void set_culled( bool culled,
std::string reason,
uint64_t iterations,
double mean,
double error,
profile_set_t::cull_error_type_e etype )
{
m_culled = culled;
m_culled_reason = std::move( reason );
m_culled_iterations = iterations;
m_culled_mean = mean;
m_culled_error = error;
m_culled_error_type = etype;
}
};

class worker_t
Expand Down
Loading