ComputationGraphBuilder Class Reference

An abstract representation of a set of Cindexes. More...

#include <nnet-computation-graph.h>

Collaboration diagram for ComputationGraphBuilder:

Classes

struct  CindexInfo
 

Public Types

enum  ComputableInfo { kUnknown = 0, kComputable = 1, kNotComputable = 2, kWillNotCompute = 3 }
 

Public Member Functions

 ComputationGraphBuilder (const Nnet &nnet, ComputationGraph *graph)
 
void Compute (const ComputationRequest &request)
 
bool AllOutputsAreComputable () const
 
void ExplainWhyAllOutputsNotComputable () const
 
void GetComputableInfo (std::vector< std::vector< bool > > *computable) const
 
void Prune ()
 

Private Member Functions

void PrintCindexId (std::ostream &os, int32 cindex_id) const
 
void ExplainWhyNotComputable (int32 cindex_id) const
 
void AddInputs ()
 
void AddOutputs ()
 
void BuildGraphOneIter ()
 
void UpdateComputableInfo (int32 cindex_id)
 
void SetAsWillNotCompute (int32 cindex_id)
 
ComputableInfo ComputeComputableInfo (int32 cindex_id) const
 
void AddCindexId (int32 cindex_id)
 
void AddDependencies (int32 cindex_id)
 
void IncrementUsableCount (int32 cindex_id)
 
void DecrementUsableCount (int32 cindex_id)
 
void PruneDependencies (int32 cindex_id)
 
void ComputeRequiredArray (int32 start_cindex_id, std::vector< bool > *required) const
 
void Check (int32 start_cindex_id) const
 

Private Attributes

const Nnetnnet_
 
const ComputationRequestrequest_
 
ComputationGraphgraph_
 
std::vector< std::vector< int32 > > depend_on_this_
 
std::vector< CindexInfocindex_info_
 
int32 current_distance_
 
std::vector< int32current_queue_
 
std::vector< int32next_queue_
 

Detailed Description

An abstract representation of a set of Cindexes.

See Building the ComputationGraph.

Definition at line 117 of file nnet-computation-graph.h.

Member Enumeration Documentation

◆ ComputableInfo

Constructor & Destructor Documentation

◆ ComputationGraphBuilder()

ComputationGraphBuilder ( const Nnet nnet,
ComputationGraph graph 
)

Definition at line 456 of file nnet-computation-graph.cc.

References ComputationGraph::cindexes, ComputationGraphBuilder::graph_, and KALDI_ASSERT.

458  :
459  nnet_(nnet), request_(NULL), graph_(graph),
460  current_distance_(-1) {
461  KALDI_ASSERT(graph_->cindexes.empty() &&
462  "ComputationGraphBuilder initialized with nonempty graph.");
463 }
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

Member Function Documentation

◆ AddCindexId()

void AddCindexId ( int32  cindex_id)
inlineprivate

Definition at line 227 of file nnet-computation-graph.cc.

References KALDI_PARANOID_ASSERT.

Referenced by ComputationGraphBuilder::AddDependencies().

227  {
228  // If this cindex_id has just now been added to the graph, the following
229  // assert should succeed.
230  KALDI_PARANOID_ASSERT(cindex_id == depend_on_this_.size() &&
231  cindex_id == cindex_info_.size());
232  depend_on_this_.push_back(std::vector<int32>());
233  cindex_info_.push_back(CindexInfo());
234 }
std::vector< std::vector< int32 > > depend_on_this_
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206

◆ AddDependencies()

void AddDependencies ( int32  cindex_id)
private

Definition at line 626 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::AddCindexId(), ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, NetworkNode::component_index, ComputationGraphBuilder::depend_on_this_, ComputationGraph::dependencies, NetworkNode::descriptor, ComputationGraph::GetCindexId(), Nnet::GetComponent(), Descriptor::GetDependencies(), Component::GetInputIndexes(), Nnet::GetNode(), ComputationGraphBuilder::graph_, rnnlm::i, ComputationGraphBuilder::IncrementUsableCount(), KALDI_ERR, kaldi::nnet3::kComponent, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, kaldi::nnet3::kInput, ComputationRequest::misc_info, ComputationGraphBuilder::next_queue_, ComputationGraphBuilder::nnet_, NetworkNode::node_index, NetworkNode::node_type, ComputationGraphBuilder::request_, kaldi::RoundUpToNearestPowerOfTwo(), kaldi::SortAndUniq(), and NetworkNode::u.

Referenced by ComputationGraphBuilder::BuildGraphOneIter().

626  {
627  if (static_cast<int32>(graph_->dependencies.size()) <= cindex_id) {
628  graph_->dependencies.resize(2 * cindex_id + 1);
629  }
630  Cindex cindex = graph_->cindexes[cindex_id];
631 
632  // find the dependencies of this cindex.
633  int32 node_index = cindex.first;
634  const Index &index = cindex.second;
635  const NetworkNode &node = nnet_.GetNode(node_index);
636 
637  std::vector<Cindex> input_cindexes;
638 
639  // the following switch statement sets up "input_cindexes".
640  switch (node.node_type) {
641  case kDescriptor: {
642  // desc describes how this node obtains its input from other nodes.
643  const Descriptor &desc = node.descriptor;
644  desc.GetDependencies(index, &input_cindexes);
645  break;
646  }
647  case kComponent: {
648  int32 c = node.u.component_index;
649  const Component *component = nnet_.GetComponent(c);
650  std::vector<Index> input_indexes;
651  component->GetInputIndexes(request_->misc_info, index,
652  &input_indexes);
653  input_cindexes.resize(input_indexes.size());
654  for (size_t i = 0; i < input_indexes.size(); i++) {
655  input_cindexes[i].first = node_index - 1; // preceding node
656  input_cindexes[i].second = input_indexes[i];
657  }
658  break;
659  }
660  case kDimRange: {
661  input_cindexes.resize(1);
662  input_cindexes[0] = Cindex(node.u.node_index, index);
663  break;
664  }
665  case kInput:
666  break; // There will be no dependencies.
667  default:
668  KALDI_ERR << "Invalid node type";
669  }
670 
671  int32 num_dependencies = input_cindexes.size();
672  // this "reserve" statement is to make sure the reference
673  // we declare below does not become invalid in the loop below
674  // (the call to graph_->GetCindexId() could add up to
675  // num_dependencies elements to the graph_->dependencies array
676  // and we want to avoid allocation).
677  // the RoundUpToNearestPowerOfTwo is for efficiency, to
678  // avoid too-frequent resizes.
680  graph_->dependencies.size() + num_dependencies));
681  std::vector<int32> &this_dep = graph_->dependencies[cindex_id];
682 
683  this_dep.resize(num_dependencies);
684  for (size_t i = 0; i < num_dependencies; i++) {
685  bool is_input = false, is_new;
686  int32 dep_cindex_id = graph_->GetCindexId(input_cindexes[i],
687  is_input, &is_new);
688  this_dep[i] = dep_cindex_id;
689  if (is_new) {
690  AddCindexId(dep_cindex_id);
691  cindex_info_.back().queued = true;
692  next_queue_.push_back(dep_cindex_id);
693  }
694  // we will keep dependent's usable_count_ up to date below
695  }
696  // remove duplicates of dependencies.
697  SortAndUniq(&this_dep);
698  // set up the "depend_on_this_" array.
699  std::vector<int32>::const_iterator iter = this_dep.begin(),
700  end = this_dep.end();
701 
702  // Populate the "depend_on_this_" array, and append the
703  // usable_count_ of things we depend on (see the definition
704  // of this quantity next to where it is declared).
705  // Note: before calling AddDependencies() we verified the following:
706  // computable_info_[cindex_id] == kUnknown
707  // and
708  // usable_count_[cindex_id] != 0
709  // which ensures that the conditions to increment the dependency's
710  // usable_count_ are satisfied.
711  for (; iter != end; ++iter) {
712  int32 dep_cindex_id = *iter;
713  depend_on_this_[dep_cindex_id].push_back(cindex_id);
714  IncrementUsableCount(dep_cindex_id);
715  }
716 }
MiscComputationInfo misc_info
misc_info is for extensibility to things that don&#39;t easily fit into the framework.
virtual void GetInputIndexes(const MiscComputationInfo &misc_info, const Index &output_index, std::vector< Index > *desired_indexes) const
This function only does something interesting for non-simple Components.
kaldi::int32 int32
int32 RoundUpToNearestPowerOfTwo(int32 n)
Definition: kaldi-math.cc:32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
std::vector< std::vector< int32 > > depend_on_this_
#define KALDI_ERR
Definition: kaldi-error.h:147
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150

◆ AddInputs()

void AddInputs ( )
private

Definition at line 254 of file nnet-computation-graph.cc.

References rnnlm::i, ComputationGraph::is_input, rnnlm::j, KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kComponent, kaldi::nnet3::kInput, and rnnlm::n.

Referenced by ComputationGraphBuilder::Compute().

254  {
255  int32 num_added = 0;
256  for (int32 i = 0; i < request_->inputs.size(); i++) {
258  if (n == -1)
259  KALDI_ERR << "Network has no input with name "
260  << request_->inputs[i].name;
262  KALDI_ASSERT((t == kInput || t == kComponent) &&
263  "Inputs to graph only allowed for Input and Component nodes.");
264 
265  for (int32 j = 0; j < request_->inputs[i].indexes.size(); j++) {
266  Cindex cindex(n, request_->inputs[i].indexes[j]);
267  bool is_input = true, is_new;
268  int32 cindex_id = graph_->GetCindexId(cindex, is_input, &is_new);
269  KALDI_ASSERT(is_new && "Input index seems to be listed more than once");
270  AddCindexId(cindex_id);
271  cindex_info_.back().computable = kComputable;
272  num_added++;
273  }
274  }
275  KALDI_ASSERT(num_added > 0 && "AddInputToGraph: nothing to add.");
276 }
kaldi::int32 int32
std::vector< IoSpecification > inputs
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 GetNodeIndex(const std::string &node_name) const
returns index associated with this node name, or -1 if no such index.
Definition: nnet-nnet.cc:466

◆ AddOutputs()

void AddOutputs ( )
private

Definition at line 278 of file nnet-computation-graph.cc.

References rnnlm::i, ComputationGraph::is_input, rnnlm::j, KALDI_ASSERT, KALDI_ERR, and rnnlm::n.

Referenced by ComputationGraphBuilder::Compute().

278  {
279  int32 num_added = 0;
280  for (int32 i = 0; i < request_->outputs.size(); i++) {
282  if (n == -1)
283  KALDI_ERR << "Network has no output with name "
284  << request_->outputs[i].name;
285  for (int32 j = 0; j < request_->outputs[i].indexes.size(); j++) {
286  Cindex cindex(n, request_->outputs[i].indexes[j]);
287  bool is_input = false, is_new;
288  int32 cindex_id = graph_->GetCindexId(cindex, is_input, &is_new);
289  KALDI_ASSERT(is_new && "Output index seems to be listed more than once");
290  AddCindexId(cindex_id);
291  cindex_info_.back().usable_count = 1;
292  cindex_info_.back().queued = true;
293  next_queue_.push_back(cindex_id);
294  num_added++;
295  }
296  }
297  if (num_added == 0) {
298  KALDI_ERR << "Cannot process computation request with no outputs";
299  }
300  current_distance_ = 0;
301  KALDI_ASSERT(current_queue_.empty());
303 }
kaldi::int32 int32
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
struct rnnlm::@11::@12 n
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< IoSpecification > outputs
int32 GetNodeIndex(const std::string &node_name) const
returns index associated with this node name, or -1 if no such index.
Definition: nnet-nnet.cc:466

◆ AllOutputsAreComputable()

bool AllOutputsAreComputable ( ) const

Definition at line 305 of file nnet-computation-graph.cc.

Referenced by Compiler::CreateComputation().

305  {
306  auto iter = cindex_info_.begin(),
307  end = cindex_info_.end();
308  for (int32 cindex_id = 0; iter != end; ++iter, ++cindex_id) {
309  if (iter->computable != kComputable) {
310  int32 network_node = graph_->cindexes[cindex_id].first;
311  if (nnet_.IsOutputNode(network_node))
312  return false;
313  }
314  }
315  return true;
316 }
kaldi::int32 int32
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112

◆ BuildGraphOneIter()

void BuildGraphOneIter ( )
private

Definition at line 896 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::AddDependencies(), ComputationGraphBuilder::cindex_info_, ComputationGraphBuilder::current_distance_, ComputationGraphBuilder::current_queue_, ComputationGraphBuilder::kUnknown, ComputationGraphBuilder::next_queue_, and ComputationGraphBuilder::UpdateComputableInfo().

Referenced by ComputationGraphBuilder::Compute().

896  {
897  while (!current_queue_.empty()) {
898  int32 cindex_id = current_queue_.back();
899  current_queue_.pop_back();
900  cindex_info_[cindex_id].queued = false;
901  if (!cindex_info_[cindex_id].dependencies_computed &&
902  cindex_info_[cindex_id].usable_count != 0) {
903  cindex_info_[cindex_id].dependencies_computed = true;
904  AddDependencies(cindex_id);
905  // Add to the queue so we can check whether it's computable.
906  if (!cindex_info_[cindex_id].queued) {
907  cindex_info_[cindex_id].queued = true;
908  next_queue_.push_back(cindex_id);
909  }
910  } else if (cindex_info_[cindex_id].computable == kUnknown) {
911  UpdateComputableInfo(cindex_id);
912  }
913  }
914  current_queue_.swap(next_queue_); // now next_queue_ will be empty.
916 }
kaldi::int32 int32

◆ Check()

void Check ( int32  start_cindex_id) const
private

Definition at line 496 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, ComputationGraphBuilder::ComputeComputableInfo(), count, ComputationGraphBuilder::current_queue_, ComputationGraphBuilder::depend_on_this_, ComputationGraph::dependencies, ComputationGraphBuilder::graph_, Nnet::IsOutputNode(), kaldi::IsSortedAndUniq(), rnnlm::j, KALDI_ASSERT, KALDI_ERR, ComputationGraphBuilder::kNotComputable, ComputationGraphBuilder::kUnknown, ComputationGraphBuilder::nnet_, and kaldi::RandInt().

Referenced by ComputationGraphBuilder::Compute().

496  {
497  int32 num_cindex_ids = graph_->cindexes.size();
498  for (int32 cindex_id = start_cindex_id; cindex_id < num_cindex_ids;
499  cindex_id += 1 + RandInt(0, num_cindex_ids / 100)) {
500  { // check depend_on_this.
501  std::vector<int32> depend_on_this = depend_on_this_[cindex_id];
502  int32 size = depend_on_this.size();
503  std::sort(depend_on_this.begin(), depend_on_this.end());
504  KALDI_ASSERT(IsSortedAndUniq(depend_on_this));
505  for (size_t j = 0; j < size; j++) {
506  int32 other_cindex_id = depend_on_this[j];
507  // make sure appears in appropriate dependencies array.
508  const std::vector<int32> &dep = graph_->dependencies[other_cindex_id];
509  KALDI_ASSERT(std::count(dep.begin(), dep.end(), cindex_id) == 1);
510  }
511  }
512  if (cindex_info_[cindex_id].dependencies_computed) {
513  // check dependencies.
514  std::vector<int32> dependencies = graph_->dependencies[cindex_id];
515  int32 size = dependencies.size();
516  std::sort(dependencies.begin(), dependencies.end());
517  KALDI_ASSERT(IsSortedAndUniq(dependencies));
518  for (size_t j = 0; j < size; j++) {
519  int32 dep_cindex_id = dependencies[j];
520  if (dep_cindex_id >= start_cindex_id) {
521  // make sure appears in appropriate depend_on_this_ array.
522  const std::vector<int32> &dep = depend_on_this_[dep_cindex_id];
523  KALDI_ASSERT(std::count(dep.begin(), dep.end(), cindex_id) == 1);
524  }
525  }
526  }
527 
528  {
529  // check usable_count_
530  int32 node_index = graph_->cindexes[cindex_id].first;
531  int32 usable_count = cindex_info_[cindex_id].usable_count,
532  usable_count_recomputed = nnet_.IsOutputNode(node_index) ? 1 : 0;
533  std::vector<int32> depend_on_this = depend_on_this_[cindex_id];
534  int32 size = depend_on_this.size();
535  for (size_t j = 0; j < size; j++) {
536  int32 other_cindex_id = depend_on_this[j];
537  if (cindex_info_[other_cindex_id].usable_count != 0 &&
538  cindex_info_[other_cindex_id].computable != kNotComputable)
539  usable_count_recomputed++;
540  }
541  KALDI_ASSERT(usable_count == usable_count_recomputed);
542  }
543  // check `computable`.
544  if (cindex_info_[cindex_id].dependencies_computed) {
546  ComputeComputableInfo(cindex_id);
547  // the status doesn't have to match if the stored info is kUnknown.
548  if (c != cindex_info_[cindex_id].computable &&
549  cindex_info_[cindex_id].computable != kUnknown) {
550  KALDI_ERR << "Mismatch in computable status";
551  }
552  }
553  // check `queued`.
554  // note, the following checks might be a bit slow.
555  if (RandInt(0, cindex_id) == 0) {
556  if (cindex_info_[cindex_id].queued) {
558  current_queue_.end(),
559  cindex_id) == 1);
560  } else {
562  current_queue_.end(),
563  cindex_id) == 0);
564  }
565  }
566  }
567 }
kaldi::int32 int32
const size_t count
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
std::vector< std::vector< int32 > > depend_on_this_
#define KALDI_ERR
Definition: kaldi-error.h:147
ComputableInfo ComputeComputableInfo(int32 cindex_id) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
Definition: stl-utils.h:63
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ Compute()

void Compute ( const ComputationRequest request)

Definition at line 466 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::AddInputs(), ComputationGraphBuilder::AddOutputs(), ComputationGraphBuilder::BuildGraphOneIter(), ComputationGraphBuilder::Check(), ComputationGraph::cindexes, ComputationGraphBuilder::current_distance_, ComputationGraphBuilder::current_queue_, kaldi::GetVerboseLevel(), ComputationGraphBuilder::graph_, KALDI_ERR, KALDI_VLOG, kaldi::RandInt(), ComputationGraphBuilder::request_, and ComputationGraph::segment_ends.

Referenced by Compiler::CreateComputation(), and kaldi::nnet3::EvaluateComputationRequest().

466  {
467  if (request_ != NULL && graph_->segment_ends.empty()) {
468  // this check is relevant to multi-segment (i.e. online) computations.
469  KALDI_ERR << "You are calling things in the wrong order: should be "
470  << "Compute(), Prune(), Compute, Prune(), ...";
471  }
472  int32 cur_segment_start = graph_->cindexes.size();
473  request_ = &request;
474  AddInputs();
475  AddOutputs(); // sets current_distance_ to 0.
476  // max_distance for debugging, to detect infinite recursion.
477  int32 max_distance = 10000;
478  while (current_distance_ < max_distance) {
480  // only check rarely if we're running at low verbose level.
481  if (GetVerboseLevel() >= 3 || RandInt(1, (current_distance_ + 1)) == 1)
482  Check(cur_segment_start);
483  if (current_queue_.empty()) // we're done.
484  break;
485  }
486  KALDI_VLOG(6) << "current_distance = " << current_distance_; // TEMP
487  if (current_distance_ == max_distance)
488  KALDI_ERR << "Loop detected while building computation graph (bad "
489  << "network topology?)";
490 
491  if (RandInt(1, 2 * (graph_->segment_ends.size() + 1)) == 1)
492  Check(cur_segment_start);
493 }
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
void Check(int32 start_cindex_id) const
kaldi::int32 int32
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< int32 > segment_ends
This variable is only of particular interest in a &#39;multi-segment&#39; computation, which is used while cr...
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95

◆ ComputeComputableInfo()

ComputationGraphBuilder::ComputableInfo ComputeComputableInfo ( int32  cindex_id) const
private

Definition at line 720 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, NetworkNode::component_index, NetworkNode::descriptor, ComputationGraph::GetCindexId(), Nnet::GetComponent(), Nnet::GetNode(), ComputationGraphBuilder::graph_, ComputationGraph::is_input, Component::IsComputable(), Descriptor::IsComputable(), KALDI_ERR, kaldi::nnet3::kComponent, ComputationGraphBuilder::kComputable, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, kaldi::nnet3::kInput, ComputationGraphBuilder::kNotComputable, ComputationGraphBuilder::kUnknown, ComputationRequest::misc_info, ComputationGraphBuilder::nnet_, NetworkNode::node_index, NetworkNode::node_type, ComputationGraphBuilder::request_, and NetworkNode::u.

Referenced by ComputationGraphBuilder::Check(), and ComputationGraphBuilder::UpdateComputableInfo().

721  {
722  const Cindex &cindex = graph_->cindexes[cindex_id];
723  int32 node_id = cindex.first;
724  const Index &index = cindex.second;
725  const NetworkNode &node = nnet_.GetNode(node_id);
726  switch (node.node_type) {
727  case kDescriptor: {
728  const Descriptor &desc = node.descriptor;
729  {
730  CindexSet cindex_set(*graph_, cindex_info_, false);
731  if (desc.IsComputable(index, cindex_set, NULL)) {
732  // it's computable even without counting kUnknown and kWillNotCompute
733  // inputs as computable [treat_unknown_as_computable = false] ->
734  // definitely computable.
735  return kComputable;
736  }
737  }
738  CindexSet cindex_set2(*graph_, cindex_info_, true);
739  if (!desc.IsComputable(index, cindex_set2, NULL)) {
740  // it's not computable even when counting kUnknown
741  // inputs as computable [treat_unknown_as_computable = true] ->
742  // definitely not computable.
743  return kNotComputable;
744  }
745  return kUnknown;
746  }
747  case kComponent: {
748  const Component *c = nnet_.GetComponent(node.u.component_index);
749  const int32 input_node_id = node_id - 1;
750  {
751  IndexSet index_set(*graph_, cindex_info_, input_node_id, false);
752  if (c->IsComputable(request_->misc_info, index, index_set, NULL)) {
753  // it's computable even without counting kUnknown
754  // inputs as computable [treat_unknown_as_computable = false] ->
755  // definitely computable.
756  return kComputable;
757  }
758  }
759  IndexSet index_set2(*graph_, cindex_info_, input_node_id, true);
760  if (!c->IsComputable(request_->misc_info, index, index_set2, NULL)) {
761  // it's not computable even when counting kUnknown inputs as computable
762  // [treat_unknown_as_computable = true] -> definitely not computable.
763  return kNotComputable;
764  }
765  return kUnknown;
766  }
767  case kDimRange: {
768  Cindex input_cindex(node.u.node_index, index);
769  int32 input_cindex_id = graph_->GetCindexId(input_cindex);
770  if (input_cindex_id != -1)
771  return cindex_info_[input_cindex_id].computable;
772  else
773  return kUnknown;
774  }
775  case kInput: {
776  // cindexes for input nodes that are part of the computation request will
777  // have graph_->is_input[cindex_id] == true; others will have
778  // graph_->is_input[cindex_id] == true.
779  return graph_->is_input[cindex_id] ? kComputable : kNotComputable;
780  }
781  default:
782  KALDI_ERR << "Invalid node type.";
783  return kUnknown; // suppress compiler warning.
784  }
785 }
MiscComputationInfo misc_info
misc_info is for extensibility to things that don&#39;t easily fit into the framework.
kaldi::int32 int32
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
std::vector< bool > is_input
For each Cindex this tells us whether it was provided as an input to the network. ...
#define KALDI_ERR
Definition: kaldi-error.h:147
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150

◆ ComputeRequiredArray()

void ComputeRequiredArray ( int32  start_cindex_id,
std::vector< bool > *  required 
) const
private

Definition at line 918 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, rnnlm::d, ComputationGraph::dependencies, ComputationGraphBuilder::graph_, Nnet::IsOutputNode(), KALDI_ASSERT, rnnlm::n, ComputationGraphBuilder::nnet_, and Nnet::NumNodes().

Referenced by ComputationGraphBuilder::Prune().

920  {
921 
922  int32 num_cindex_ids = graph_->cindexes.size();
923  KALDI_ASSERT(num_cindex_ids >= start_cindex_id);
924  KALDI_ASSERT(cindex_info_.size() == num_cindex_ids);
925  required->clear();
926  required->resize(num_cindex_ids - start_cindex_id, false);
927 
928  // would be bool, but indexing c++ bool may be slow.
929  std::vector<char> is_output_node(nnet_.NumNodes());
930  for (int32 n = 0; n < nnet_.NumNodes(); n++)
931  is_output_node[n] = (char)(nnet_.IsOutputNode(n) ? 1 : 0);
932 
933  std::vector<int32> queue;
934  for (int32 c = start_cindex_id; c < num_cindex_ids; c++) {
935  // First put the output cindex_ids into the queue.
936  int32 node_id = graph_->cindexes[c].first;
937  if (is_output_node[node_id]) {
938  (*required)[c - start_cindex_id] = true;
939  queue.push_back(c);
940  }
941  }
942  while (!queue.empty()) {
943  int32 c = queue.back();
944  queue.pop_back();
945  const std::vector<int32> &dependencies = graph_->dependencies[c];
946  std::vector<int32>::const_iterator iter = dependencies.begin(),
947  end = dependencies.end();
948  for (; iter != end; ++iter) {
949  int32 d = *iter;
950  if (d >= start_cindex_id && !(*required)[d - start_cindex_id]){
951  (*required)[d - start_cindex_id] = true;
952  queue.push_back(d);
953  }
954  }
955  }
956  // just check that we don't have any cindex_ids which are required but have
957  // usable_count_ == 0; this would indicate a bug somewhere.
958  for (int32 c = start_cindex_id; c < num_cindex_ids; c++)
959  KALDI_ASSERT(!((*required)[c - start_cindex_id] &&
960  (cindex_info_[c].usable_count == 0)));
961 
962 }
int32 NumNodes() const
Definition: nnet-nnet.h:126
kaldi::int32 int32
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ DecrementUsableCount()

void DecrementUsableCount ( int32  cindex_id)
private

Definition at line 881 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::dependencies, ComputationGraphBuilder::graph_, KALDI_PARANOID_ASSERT, and ComputationGraphBuilder::kNotComputable.

Referenced by ComputationGraphBuilder::UpdateComputableInfo().

881  {
882  KALDI_PARANOID_ASSERT(cindex_info_[cindex_id].usable_count > 0);
883  if (--cindex_info_[cindex_id].usable_count == 0 &&
884  cindex_info_[cindex_id].computable != kNotComputable) {
885  std::vector<int32>::const_iterator
886  iter = graph_->dependencies[cindex_id].begin(),
887  end = graph_->dependencies[cindex_id].end();
888  for (; iter != end; ++iter) {
889  int32 dep_cindex_id = *iter;
890  DecrementUsableCount(dep_cindex_id);
891  }
892  }
893 }
kaldi::int32 int32
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206

◆ ExplainWhyAllOutputsNotComputable()

void ExplainWhyAllOutputsNotComputable ( ) const

Definition at line 334 of file nnet-computation-graph.cc.

References rnnlm::i, KALDI_ASSERT, and KALDI_LOG.

Referenced by Compiler::CreateComputation().

334  {
335  std::vector<int32> outputs_not_computable;
336  int32 num_outputs_total = 0;
337 
338  std::vector<Cindex>::const_iterator iter = graph_->cindexes.begin(),
339  end = graph_->cindexes.end();
340  for (int32 cindex_id = 0; iter != end; ++iter,++cindex_id) {
341  int32 network_node = iter->first;
342  if (nnet_.IsOutputNode(network_node)) {
343  num_outputs_total++;
344  if (cindex_info_[cindex_id].computable != kComputable)
345  outputs_not_computable.push_back(cindex_id);
346  }
347  }
348  KALDI_ASSERT(!outputs_not_computable.empty() &&
349  "You called this function when everything was computable.");
350  int32 num_print = 10, num_not_computable = outputs_not_computable.size();
351  KALDI_LOG << num_not_computable << " output cindexes out of "
352  << num_outputs_total << " were not computable.";
353  std::ostringstream os;
354  request_->Print(os);
355  KALDI_LOG << "Computation request was: " << os.str();
356  if (num_not_computable > num_print)
357  KALDI_LOG << "Printing the reasons for " << num_print << " of these.";
358  for (int32 i = 0; i < num_not_computable && i < num_print; i++)
359  ExplainWhyNotComputable(outputs_not_computable[i]);
360 }
void ExplainWhyNotComputable(int32 cindex_id) const
kaldi::int32 int32
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void Print(std::ostream &os) const
This function is for printing info about the computation request in a human-readable way...
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ ExplainWhyNotComputable()

void ExplainWhyNotComputable ( int32  cindex_id) const
private

Definition at line 134 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::CindexInfo::computable, ComputationGraph::dependencies, KALDI_ASSERT, and KALDI_LOG.

135  {
136  int32 max_lines_print = 100;
137  std::deque<int32> cindexes_to_explain;
138  std::vector<bool> added_to_queue(graph_->cindexes.size(), false);
139  cindexes_to_explain.push_back(first_cindex_id);
140  added_to_queue[first_cindex_id] = true;
141  KALDI_ASSERT(graph_->cindexes.size() == graph_->dependencies.size());
142  std::ostringstream os;
143  os << "*** cindex ";
144  PrintCindexId(os, first_cindex_id);
145  os << " is not computable for the following reason: ***\n";
146  for (int32 num_lines_printed = 0;
147  num_lines_printed < max_lines_print && !cindexes_to_explain.empty();
148  num_lines_printed++) {
149  int32 cindex_id = cindexes_to_explain.front();
150  cindexes_to_explain.pop_front();
151  KALDI_ASSERT(static_cast<size_t>(cindex_id) < graph_->cindexes.size());
152  PrintCindexId(os, cindex_id);
153  os << " is " << cindex_info_[cindex_id].computable << ", dependencies: ";
154  const std::vector<int32> dependencies = graph_->dependencies[cindex_id];
155  std::vector<int32>::const_iterator iter = dependencies.begin(),
156  end = dependencies.end();
157  for (; iter != end; iter++) {
158  int32 dep_cindex_id = *iter;
159  PrintCindexId(os, dep_cindex_id);
160  const CindexInfo &dep_info = cindex_info_[dep_cindex_id];
161  os << '[' << dep_info.computable << ']';
162  if (dep_info.computable != kComputable && !added_to_queue[dep_cindex_id]) {
163  added_to_queue[dep_cindex_id] = true;
164  cindexes_to_explain.push_back(dep_cindex_id);
165  }
166  if (iter+2 != end)
167  os << ", ";
168  }
169  os << "\n";
170  }
171  os << "\n";
172  KALDI_LOG << os.str();
173 }
void PrintCindexId(std::ostream &os, int32 cindex_id) const
kaldi::int32 int32
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ GetComputableInfo()

void GetComputableInfo ( std::vector< std::vector< bool > > *  computable) const

Definition at line 787 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, ComputationGraph::GetCindexId(), Nnet::GetNodeIndex(), ComputationGraphBuilder::graph_, rnnlm::i, IoSpecification::indexes, rnnlm::j, KALDI_ASSERT, ComputationGraphBuilder::kComputable, rnnlm::n, IoSpecification::name, ComputationGraphBuilder::nnet_, ComputationRequest::outputs, and ComputationGraphBuilder::request_.

Referenced by kaldi::nnet3::EvaluateComputationRequest().

788  {
789  KALDI_ASSERT(!graph_->cindexes.empty() &&
790  "You need to call this after Compute()!");
791  KALDI_ASSERT(!cindex_info_.empty() &&
792  "You need to call this before Prune()!");
793  computable->clear();
794  computable->resize(request_->outputs.size());
795  for (size_t i = 0; i < request_->outputs.size(); i++) {
796  const IoSpecification &output = request_->outputs[i];
797  int32 n = nnet_.GetNodeIndex(output.name);
798  KALDI_ASSERT(n != -1);
799  int32 size = output.indexes.size();
800  std::vector<bool> &this_vec = (*computable)[i];
801  this_vec.resize(size);
802  for (size_t j = 0; j < size; j++) {
803  Cindex cindex(n, output.indexes[j]);
804  int32 cindex_id = graph_->GetCindexId(cindex);
805  KALDI_ASSERT(cindex_id != -1);
806  this_vec[j] = (cindex_info_[cindex_id].computable == kComputable);
807  }
808  }
809 }
kaldi::int32 int32
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
struct rnnlm::@11::@12 n
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< IoSpecification > outputs
int32 GetNodeIndex(const std::string &node_name) const
returns index associated with this node name, or -1 if no such index.
Definition: nnet-nnet.cc:466

◆ IncrementUsableCount()

void IncrementUsableCount ( int32  cindex_id)
private

Definition at line 859 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraphBuilder::CindexInfo::computable, ComputationGraph::dependencies, ComputationGraphBuilder::graph_, ComputationGraphBuilder::kNotComputable, ComputationGraphBuilder::kUnknown, ComputationGraphBuilder::next_queue_, ComputationGraphBuilder::CindexInfo::queued, and ComputationGraphBuilder::CindexInfo::usable_count.

Referenced by ComputationGraphBuilder::AddDependencies().

859  {
860  CindexInfo &info = cindex_info_[cindex_id];
861  if (info.usable_count++ == 0 &&
862  info.computable != kNotComputable) {
863  std::vector<int32>::const_iterator
864  iter = graph_->dependencies[cindex_id].begin(),
865  end = graph_->dependencies[cindex_id].end();
866  for (; iter != end; ++iter) {
867  int32 dep_cindex_id = *iter;
868  IncrementUsableCount(dep_cindex_id);
869  }
870  if (info.computable == kUnknown &&
871  !info.queued) {
872  // It's become usable, so make sure it's queued to process whether it is
873  // computable or not.
874  info.queued = true;
875  next_queue_.push_back(cindex_id);
876  }
877  }
878 }
kaldi::int32 int32
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...

◆ PrintCindexId()

void PrintCindexId ( std::ostream &  os,
int32  cindex_id 
) const
private

Definition at line 125 of file nnet-computation-graph.cc.

References KALDI_ASSERT.

126  {
127  KALDI_ASSERT(static_cast<size_t>(cindex_id) < graph_->cindexes.size());
128  const Cindex &cindex = graph_->cindexes[cindex_id];
129  const std::string &node_name = nnet_.GetNodeName(cindex.first);
130  os << node_name << '(' << cindex.second.n << ", " << cindex.second.t
131  << ", " << cindex.second.x << ')';
132 }
const std::string & GetNodeName(int32 node_index) const
returns individual node name.
Definition: nnet-nnet.cc:684
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ Prune()

void Prune ( )

Definition at line 569 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraph::cindexes, ComputationGraphBuilder::ComputeRequiredArray(), ComputationGraphBuilder::depend_on_this_, ComputationGraphBuilder::graph_, rnnlm::i, ComputationGraph::is_input, KALDI_ASSERT, ComputationGraphBuilder::kComputable, ComputationGraphBuilder::PruneDependencies(), ComputationGraph::Renumber(), and ComputationGraph::segment_ends.

Referenced by Compiler::CreateComputation().

569  {
570  // Since Prune() is called for each segment in turn [note: there
571  // will be only 1 segment in the normal non-online case], we
572  // only prune for the current, just-added segment.
573  int32 start_cindex_id = (graph_->segment_ends.empty() ? 0 :
574  graph_->segment_ends.back());
575  int32 num_cindex_ids = graph_->cindexes.size();
576  // Prune the dependencies to just those that are used (to remove
577  // optional dependencies that don't end up getting used).
578 
579  for (int32 cindex_id = start_cindex_id;
580  cindex_id < num_cindex_ids; cindex_id++)
581  PruneDependencies(cindex_id);
582  // the following clears the elements of depend_on_this from start_cindex_id to
583  // num_cindex_ids - 1, without touching the entire array.
584  depend_on_this_.resize(start_cindex_id);
585  depend_on_this_.resize(num_cindex_ids);
586  std::vector<bool> required;
587  ComputeRequiredArray(start_cindex_id, &required);
588 
589  std::vector<bool> keep(num_cindex_ids - start_cindex_id, false);
590  for (int32 c = start_cindex_id; c < num_cindex_ids; c++) {
591  if (required[c - start_cindex_id] || graph_->is_input[c]) {
592  KALDI_ASSERT(cindex_info_[c].computable == kComputable &&
593  "You are calling Prune when not everything is computable.");
594  keep[c - start_cindex_id] = true;
595  }
596  }
597  graph_->Renumber(start_cindex_id, keep);
598  // We also need to renumber cindex_info_ b,
599  // graph_->Renumber doesn't do for us, but we can make some shortcuts. We set
600  // all computable_info_ to kComputable because actually it all was kComputable
601  // (we checked when deciding what to keep); and we set the usable_count_ to 1
602  // for all the cindex_ids we just added... this is not 100% accurate
603  // according to the way we defined usable_count_, but it prevents additional
604  // computation since it is > 0 (notice that IncrementUsableCount and
605  // DecrementUsableCount may do some work when the usable_count goes to zero or
606  // from zero. Anyway, the usable-count for these cindex_ids for those "older
607  // segments" is not critical. [this information only gets used if we process
608  // additional segments as part of the compilation of an online computation.]
609  int32 new_num_cindex_ids = graph_->cindexes.size();
610  cindex_info_.resize(start_cindex_id);
611  cindex_info_.resize(new_num_cindex_ids);
612  for (int32 i = start_cindex_id; i < new_num_cindex_ids; i++) {
613  cindex_info_[i].computable = kComputable;
614  cindex_info_[i].usable_count = 1;
615  }
616  // depend_on_this_ is a vector of vectors-- keeping track of the reverse of
617  // the dependencies-- and I believe we won't be needing this information any
618  // more past this point.
619  depend_on_this_.resize(start_cindex_id);
620  depend_on_this_.resize(new_num_cindex_ids);
621 
622  graph_->segment_ends.push_back(new_num_cindex_ids);
623 }
kaldi::int32 int32
void ComputeRequiredArray(int32 start_cindex_id, std::vector< bool > *required) const
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
std::vector< bool > is_input
For each Cindex this tells us whether it was provided as an input to the network. ...
std::vector< std::vector< int32 > > depend_on_this_
std::vector< int32 > segment_ends
This variable is only of particular interest in a &#39;multi-segment&#39; computation, which is used while cr...
void Renumber(int32 start_cindex_id, const std::vector< bool > &keep)
This function renumbers the cindex-ids (but only those with index c >= start_cindex_id,.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ PruneDependencies()

void PruneDependencies ( int32  cindex_id)
private

Definition at line 367 of file nnet-computation-graph.cc.

References NetworkNode::component_index, ComputationGraphBuilder::CindexInfo::computable, ComputationGraph::dependencies, NetworkNode::descriptor, rnnlm::i, Component::IsComputable(), Descriptor::IsComputable(), KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kComponent, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, kaldi::nnet3::kInput, NetworkNode::node_type, kaldi::SortAndUniq(), NetworkNode::u, and ComputationGraphBuilder::CindexInfo::usable_count.

Referenced by ComputationGraphBuilder::Prune().

367  {
368  const CindexInfo &info = cindex_info_[cindex_id];
369  // by the time this is called, there should be no cindexes with unknown state
370  // that are usable.
371  KALDI_ASSERT(!(info.computable == kUnknown && info.usable_count != 0));
372  if (info.computable == kNotComputable || info.usable_count == 0) {
373  // if something is not computable or is not usable, there is no point
374  // keeping around its dependencies.
375  graph_->dependencies[cindex_id].clear();
376  return;
377  }
378  KALDI_ASSERT(info.computable == kComputable);
379  const Cindex &cindex = graph_->cindexes[cindex_id];
380  int32 node_id = cindex.first;
381  const Index &index = cindex.second;
382  const NetworkNode &node = nnet_.GetNode(node_id);
383 
384  std::vector<int32> &dependencies = graph_->dependencies[cindex_id];
385  std::sort(dependencies.begin(), dependencies.end());
386  std::vector<int32> used_cindex_ids;
387 
388  switch (node.node_type) {
389  case kDescriptor: {
390  const Descriptor &desc = node.descriptor;
391  bool dont_care = false; // there should be no kUnknown, and we check this
392  CindexSet cindex_set(*graph_, cindex_info_, dont_care);
393  std::vector<Cindex> used_cindexes;
394  bool ans = desc.IsComputable(index, cindex_set, &used_cindexes);
395  // If the next assert fails it could be a failure in the assumption that
396  // making more inputs available will never change something from not being
397  // computable to being computable; or it could be a bug elsewhere.
398  KALDI_ASSERT(ans);
399  size_t size = used_cindexes.size();
400  used_cindex_ids.resize(size);
401  for (size_t i = 0; i < size; i++) {
402  int32 dep_cindex_id = graph_->GetCindexId(used_cindexes[i]);
403  KALDI_ASSERT(dep_cindex_id != -1);
404  used_cindex_ids[i] = dep_cindex_id;
405  KALDI_ASSERT(std::binary_search(dependencies.begin(),
406  dependencies.end(),
407  dep_cindex_id));
408  }
409  break;
410  }
411  case kComponent: {
412  const Component *c = nnet_.GetComponent(node.u.component_index);
413  bool dont_care = false; // there should be no kUnknown, and we check this
414  // In the line below, node_id - 1 is the index of the component-input
415  // node-- the descriptor at the input to the component. We are interested
416  // in the set of inputs to the component that are computable.
417  IndexSet index_set(*graph_, cindex_info_, node_id - 1, dont_care);
418  std::vector<Index> used_indexes;
419  bool ans = c->IsComputable(request_->misc_info, index, index_set,
420  &used_indexes);
421  // If the next assert fails it could be a failure in the assumption that
422  // making more inputs available will never change something from not being
423  // computable to being computable; or it could be a bug elsewhere.
424  KALDI_ASSERT(ans);
425  size_t size = used_indexes.size();
426  used_cindex_ids.resize(size);
427  for (size_t i = 0; i < size; i++) {
428  Cindex dep_cindex(node_id - 1, used_indexes[i]);
429  int32 dep_cindex_id = graph_->GetCindexId(dep_cindex);
430  KALDI_ASSERT(dep_cindex_id != -1);
431  used_cindex_ids[i] = dep_cindex_id;
432  KALDI_ASSERT(std::binary_search(dependencies.begin(),
433  dependencies.end(),
434  dep_cindex_id));
435  }
436  break;
437  }
438  case kDimRange:
439  KALDI_ASSERT(dependencies.size() == 1);
440  // there should be exactly one dependency and it is required, not
441  // optional, so there is nothing to do here. Return.
442  return;
443  case kInput:
444  KALDI_ASSERT(dependencies.empty());
445  // there is nothing to do; return.
446  return;
447  default:
448  KALDI_ERR << "Invalid node type";
449  }
450  SortAndUniq(&used_cindex_ids);
451 
452  // the next statement modifies the graph.
453  dependencies.swap(used_cindex_ids);
454 }
MiscComputationInfo misc_info
misc_info is for extensibility to things that don&#39;t easily fit into the framework.
kaldi::int32 int32
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
std::pair< int32, Index > Cindex
Definition: nnet-common.h:115
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
#define KALDI_ERR
Definition: kaldi-error.h:147
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ SetAsWillNotCompute()

void SetAsWillNotCompute ( int32  cindex_id)
private

◆ UpdateComputableInfo()

void UpdateComputableInfo ( int32  cindex_id)
private

Definition at line 812 of file nnet-computation-graph.cc.

References ComputationGraphBuilder::cindex_info_, ComputationGraphBuilder::ComputeComputableInfo(), ComputationGraphBuilder::DecrementUsableCount(), ComputationGraphBuilder::depend_on_this_, ComputationGraph::dependencies, ComputationGraphBuilder::graph_, KALDI_ASSERT, ComputationGraphBuilder::kNotComputable, ComputationGraphBuilder::kUnknown, and ComputationGraphBuilder::next_queue_.

Referenced by ComputationGraphBuilder::BuildGraphOneIter().

812  {
813  // if the current computable_info_ for cindex_id value is not kUnknown, this
814  // cindex_id should not have been in the queue.
815  KALDI_ASSERT(static_cast<size_t>(cindex_id) < cindex_info_.size());
816 
817  // We don't need to update the computable info of this node since it's
818  // not usable (i.e. not currently reachable from any node that is not
819  // kNotComputable).
820  if (cindex_info_[cindex_id].usable_count == 0)
821  return;
822 
823  ComputableInfo &output = cindex_info_[cindex_id].computable;
824  KALDI_ASSERT(output == kUnknown);
825 
826  output = ComputeComputableInfo(cindex_id);
827 
828  if (output != kUnknown) {
829  // The computable status of cindexes that depend on this cindex and whose
830  // status is currently kUnknown might now change, so if they are not in the
831  // computable queue, put them there.
832  std::vector<int32>::const_iterator iter = depend_on_this_[cindex_id].begin(),
833  end = depend_on_this_[cindex_id].end();
834  for (; iter != end; ++iter) {
835  int32 other_cindex_id = *iter;
836  if (cindex_info_[other_cindex_id].computable == kUnknown &&
837  !cindex_info_[other_cindex_id].queued) {
838  cindex_info_[other_cindex_id].queued = true;
839  next_queue_.push_back(other_cindex_id);
840  }
841  }
842  if (output == kNotComputable && cindex_info_[cindex_id].usable_count != 0) {
843  // If we have just changed the computable state from kUnknown to
844  // kNotComputable, then given the way the usable_count is defined (see
845  // the declaration), this means that we must decrement the
846  // usable_count_ of all cindex_ids that we depend on.
847  std::vector<int32>::const_iterator
848  iter = graph_->dependencies[cindex_id].begin(),
849  end = graph_->dependencies[cindex_id].end();
850  for (; iter != end; ++iter) {
851  int32 dep_cindex_id = *iter;
852  DecrementUsableCount(dep_cindex_id);
853  }
854  }
855  }
856 }
kaldi::int32 int32
std::vector< std::vector< int32 > > dependencies
dependencies[cindex_id] gives you the list of other cindex_ids that this particular cindex_id directl...
std::vector< std::vector< int32 > > depend_on_this_
ComputableInfo ComputeComputableInfo(int32 cindex_id) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

Member Data Documentation

◆ cindex_info_

◆ current_distance_

int32 current_distance_
private

◆ current_queue_

◆ depend_on_this_

◆ graph_

◆ next_queue_

◆ nnet_

◆ request_


The documentation for this class was generated from the following files: