Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sampling period for computing the rolling average real time factor #758

Merged
merged 9 commits into from
May 8, 2024
10 changes: 10 additions & 0 deletions include/cosim/timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ struct real_time_config
* This value is used for monitoring purposes only.
*/
std::atomic<int> steps_to_monitor = 5;

/**
* A sampling period in real time (wall clock) in milliseconds used in the rolling average real time factor calculation.
* This can be useful when simulation step size is small and a fixed value for `steps_to_monitor`
* would not compute an accurate rolling average real time factor.
* When the value is greater than zero, the real time factor is computed periodically using the
* specified time instead of the `steps_to_monitor` value.
*/
std::atomic<std::chrono::milliseconds> sampling_period_to_monitor = std::chrono::milliseconds(-1);
};

} // namespace cosim
Expand All @@ -54,6 +63,7 @@ class hash<cosim::real_time_config>
boost::hash_combine(seed, v.real_time_simulation.load());
boost::hash_combine(seed, v.real_time_factor_target.load());
boost::hash_combine(seed, v.steps_to_monitor.load());
boost::hash_combine(seed, v.sampling_period_to_monitor.load().count());
return seed;
}
};
Expand Down
41 changes: 32 additions & 9 deletions src/cosim/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include <chrono>
#include <thread>

typedef std::chrono::steady_clock Time;
constexpr std::chrono::microseconds MIN_SLEEP(100);

Expand Down Expand Up @@ -37,6 +36,12 @@ class real_time_timer::impl
const auto newHash = std::hash<real_time_config>()(*config_);
if (newHash != configHashValue_) {
start(currentTime);
const auto sampling_period = config_->sampling_period_to_monitor.load();
if (sampling_period.count() > 0) {
sampling_period_to_monitor_ = sampling_period;
} else {
sampling_period_to_monitor_ = std::nullopt;
}
configHashValue_ = newHash;
}
double rtfTarget = config_->real_time_factor_target.load();
Expand Down Expand Up @@ -72,21 +77,39 @@ class real_time_timer::impl
std::shared_ptr<real_time_config> config_;
size_t configHashValue_;
std::shared_ptr<real_time_metrics> metrics_;
std::optional<std::chrono::milliseconds> sampling_period_to_monitor_ = std::nullopt;

template<typename Rep, typename Period>
void update_rolling_average_real_time_factor(
const Time::time_point& currentTime,
const time_point& currentSimulationTime,
const std::chrono::duration<Rep, Period>& elapsedRealTime)
{
const auto elapsedSimTime = currentSimulationTime - rtSimulationStartTime_;

metrics_->rolling_average_real_time_factor =
std::chrono::duration_cast<cosim::duration>(elapsedSimTime).count() / (1.0 * std::chrono::duration_cast<cosim::duration>(elapsedRealTime).count());
rtStartTime_ = currentTime;
rtSimulationStartTime_ = currentSimulationTime;
rtCounter_ = 0L;
}

void update_real_time_factor(Time::time_point currentTime, time_point currentSimulationTime)
{
const auto relativeSimTime = currentSimulationTime - simulationStartTime_;
const auto relativeRealTime = currentTime - startTime_;
const auto relativeSimTime = std::chrono::duration_cast<cosim::duration>(currentSimulationTime - simulationStartTime_);
const auto relativeRealTime = std::chrono::duration_cast<cosim::duration>(currentTime - startTime_);
metrics_->total_average_real_time_factor = relativeSimTime.count() / (1.0 * relativeRealTime.count());

if (rtCounter_ >= config_->steps_to_monitor.load()) {
const auto elapsedSimTime = currentSimulationTime - rtSimulationStartTime_;
if (sampling_period_to_monitor_.has_value()) {
const auto elapsedRealTime = currentTime - rtStartTime_;

metrics_->rolling_average_real_time_factor = elapsedSimTime.count() / (1.0 * elapsedRealTime.count());
rtStartTime_ = currentTime;
rtSimulationStartTime_ = currentSimulationTime;
rtCounter_ = 0L;
if (elapsedRealTime > sampling_period_to_monitor_.value()) {
const auto elapsedSimTime = currentSimulationTime - rtSimulationStartTime_;
update_rolling_average_real_time_factor(currentTime, currentSimulationTime, elapsedRealTime);
}
} else if (rtCounter_ >= config_->steps_to_monitor.load()) {
const auto elapsedRealTime = currentTime - rtStartTime_;
update_rolling_average_real_time_factor(currentTime, currentSimulationTime, elapsedRealTime);
}
rtCounter_++;
}
Expand Down