Skip to content

Commit

Permalink
[framework] Improve DiagramBuilder::Build performance (#19746)
Browse files Browse the repository at this point in the history
When searching the Diagram feedthrough graph, only ever ask each
subsystem for its own feedthrough graph at most once.
  • Loading branch information
jwnimmer-tri authored Jul 20, 2023
1 parent c139b63 commit 894ac55
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
23 changes: 18 additions & 5 deletions systems/framework/diagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ Diagram<T>::get_output_port_locator(OutputPortIndex port_index) const {

template <typename T>
std::multimap<int, int> Diagram<T>::GetDirectFeedthroughs() const {
std::unordered_map<const System<T>*, std::multimap<int, int>> memoize;
std::multimap<int, int> pairs;
for (InputPortIndex u(0); u < this->num_input_ports(); ++u) {
for (OutputPortIndex v(0); v < this->num_output_ports(); ++v) {
if (DiagramHasDirectFeedthrough(u, v)) {
if (DiagramHasDirectFeedthrough(u, v, &memoize)) {
pairs.emplace(u, v);
}
}
Expand Down Expand Up @@ -1090,12 +1091,15 @@ const SystemBase& Diagram<T>::GetRootSystemBase() const {
}

template <typename T>
bool Diagram<T>::DiagramHasDirectFeedthrough(int input_port, int output_port)
bool Diagram<T>::DiagramHasDirectFeedthrough(
int input_port, int output_port,
std::unordered_map<const System<T>*, std::multimap<int, int>>* memoize)
const {
DRAKE_ASSERT(input_port >= 0);
DRAKE_ASSERT(input_port < this->num_input_ports());
DRAKE_ASSERT(output_port >= 0);
DRAKE_ASSERT(output_port < this->num_output_ports());
DRAKE_ASSERT(memoize != nullptr);

const auto input_ids = GetInputPortLocators(InputPortIndex(input_port));
std::set<InputPortLocator> target_input_ids(input_ids.begin(),
Expand All @@ -1108,10 +1112,19 @@ bool Diagram<T>::DiagramHasDirectFeedthrough(int input_port, int output_port)
active_set.insert(output_port_ids_[output_port]);
while (!active_set.empty()) {
const OutputPortLocator current_output_id = *active_set.begin();
size_t removed_count = active_set.erase(current_output_id);
const size_t removed_count = active_set.erase(current_output_id);
DRAKE_ASSERT(removed_count == 1);
const System<T>* sys = current_output_id.first;
for (const auto& [sys_input, sys_output] : sys->GetDirectFeedthroughs()) {
const System<T>* const sys = current_output_id.first;
auto memoized_feedthroughs = memoize->find(sys);
if (memoized_feedthroughs == memoize->end()) {
bool inserted{};
std::tie(memoized_feedthroughs, inserted) =
memoize->emplace(sys, sys->GetDirectFeedthroughs());
DRAKE_ASSERT(inserted);
}
const std::multimap<int, int>& sys_feedthroughs =
memoized_feedthroughs->second;
for (const auto& [sys_input, sys_output] : sys_feedthroughs) {
if (sys_output == current_output_id.second) {
const InputPortLocator curr_input_id(sys, sys_input);
if (target_input_ids.count(curr_input_id)) {
Expand Down
10 changes: 8 additions & 2 deletions systems/framework/diagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -400,8 +401,13 @@ class Diagram : public System<T>, internal::SystemParentServiceInterface {
const SystemBase& GetRootSystemBase() const final;

// Returns true if there might be direct feedthrough from the given
// @p input_port of the Diagram to the given @p output_port of the Diagram.
bool DiagramHasDirectFeedthrough(int input_port, int output_port) const;
// `input_port` of the Diagram to the given `output_port` of the Diagram.
// The `memoize` dictionary caches the subsystem's reported feedthrough,
// to accelerate repeated calls to this function.
bool DiagramHasDirectFeedthrough(
int input_port, int output_port,
std::unordered_map<const System<T>*, std::multimap<int, int>>* memoize)
const;

// Allocates a collection of homogeneous events (e.g., publish events) for
// this Diagram.
Expand Down

0 comments on commit 894ac55

Please sign in to comment.