All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Compiler Class Reference

This class creates an initial version of the NnetComputation, without any optimization or sharing of matrices. More...

#include <nnet-compile.h>

Collaboration diagram for Compiler:

Classes

struct  StepInfo
 

Public Member Functions

 Compiler (const ComputationRequest &request, const Nnet &nnet)
 
 Compiler (const std::vector< const ComputationRequest * > &request, const Nnet &nnet)
 
void CreateComputation (const CompilerOptions &opts, NnetComputation *computation)
 

Private Member Functions

void ComputeStepDependencies (const std::vector< int32 > &this_step, int32 step_index, unordered_set< int32 > *dep_steps)
 
void ComputeDerivNeeded (const std::vector< std::vector< int32 > > &steps, const std::vector< int32 > &step_to_segment, std::vector< bool > *deriv_needed)
 
void CreateStepInfo (const std::vector< bool > &deriv_needed, const std::vector< int32 > &step_to_segment, std::vector< std::vector< int32 > > *by_step, NnetComputation *computation)
 
MatrixStrideType GetStrideType (int32 node_index) const
 
void DefineMatrices (NnetComputation *computation) const
 
void DefineSubmatrices (NnetComputation *computation)
 
void AllocateMatrices (const std::vector< int32 > &whole_submatrices, NnetComputation *computation) const
 
void SetUpPrecomputedIndexes (const std::vector< int32 > &step_to_segment, NnetComputation *computation)
 
void CompileForward (int32 step, NnetComputation *computation) const
 
void AddForwardStepComponent (int32 step, NnetComputation *computation) const
 
void AddForwardStepInput (int32 step, NnetComputation *computation) const
 
bool IsInputStep (int32 step) const
 
void CompileForwardDescriptor (int32 step, NnetComputation *computation) const
 
void CompileForwardSumDescriptor (int32 step, int32 part_index, NnetComputation *computation) const
 
void ComputeInputLocationsList (int32 step, int32 part_index, std::vector< std::vector< std::pair< int32, int32 > > > *input_locations) const
 
BaseFloat SplitByScale (const SumDescriptor &descriptor, const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::pair< BaseFloat, std::vector< std::vector< std::pair< int32, int32 > > > > > *split_locations_lists) const
 This function helps to handle scalar factors in Descriptors (expressions like `Scale(-1.0, <descriptor)`). More...
 
void ComputeValueSubmatLocationsList (const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
 
void ComputeDerivSubmatLocationsList (const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
 
void CompileForwardFromSubmatLocationsList (int32 value_submatrix_index, BaseFloat alpha, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
 Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor. More...
 
void CompileForwardFromSubmatLocations (int32 value_submatrix_index, BaseFloat alpha, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
 Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor. More...
 
void CompileForwardFromIndexes (int32 value_submatrix_index, int32 input_submatrix_index, BaseFloat alpha, const std::vector< int32 > &indexes, NnetComputation *computation) const
 Adds to `computation` a command that adds to the submatrix in `value_submatrix_index` a quantity consisting of alpha times the submatrix in `input_submatrix_index`, with a row mapping given by `indexes`. More...
 
void CompileBackward (int32 step, NnetComputation *computation)
 
void AddBackwardStepComponent (int32 step, NnetComputation *computation) const
 
void AddBackwardStepInput (int32 step, NnetComputation *computation) const
 
void CompileBackwardDescriptor (int32 step, NnetComputation *computation)
 
void CompileBackwardSumDescriptor (int32 step, int32 part_index, NnetComputation *computation) const
 
void CompileBackwardFromSubmatLocationsList (int32 deriv_submatrix_index, BaseFloat alpha, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
 
void CompileBackwardFromSubmatLocations (int32 deriv_submatrix_index, BaseFloat alpha, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
 
void CompileBackwardFromIndexes (int32 deriv_submatrix_index, int32 input_deriv_submatrix_index, BaseFloat alpha, const std::vector< int32 > &indexes, NnetComputation *computation) const
 
void DeallocateMatrices (const std::vector< int32 > &whole_submatrices, const std::vector< int32 > &step_to_segment, NnetComputation *computation)
 
void OutputDebugInfo (NnetComputation *computation) const
 
void AddCommands (const std::vector< bool > &deriv_needed, const std::vector< int32 > &step_to_segment, NnetComputation *computation)
 

Private Attributes

std::vector< const
ComputationRequest * > 
requests_
 
const Nnetnnet_
 
ComputationGraph graph_
 
std::vector< StepInfosteps_
 
std::vector< std::pair< int32,
int32 > > 
cindex_id_to_location_
 This maps each cindex_id to its location. More...
 

Detailed Description

This class creates an initial version of the NnetComputation, without any optimization or sharing of matrices.

Note: for a user-level interface that includes optimization, see class CachingOptimizingCompiler in nnet-optimize.h.

Definition at line 44 of file nnet-compile.h.

Constructor & Destructor Documentation

Compiler ( const ComputationRequest request,
const Nnet nnet 
)

Definition at line 29 of file nnet-compile.cc.

References Compiler::requests_.

31  : nnet_(nnet) {
32  requests_.push_back(&request);
33 }
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
Compiler ( const std::vector< const ComputationRequest * > &  request,
const Nnet nnet 
)

Definition at line 35 of file nnet-compile.cc.

References rnnlm::i, KALDI_ASSERT, and Compiler::requests_.

37  : requests_(requests), nnet_(nnet) {
38  KALDI_ASSERT(requests_.size() >= 1);
39  // We are currently not supporting getting model derivatives for multi-segment
40  // (online) computations.
41  if (requests_.size() != 1) {
42  for (size_t i = 0; i < requests_.size(); i++) {
43  KALDI_ASSERT(!requests_[i]->need_model_derivative);
44  KALDI_ASSERT(requests_[i]->store_component_stats ==
45  requests_[0]->store_component_stats);
46  }
47  }
48 }
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169

Member Function Documentation

void AddBackwardStepComponent ( int32  step,
NnetComputation computation 
) const
private

Definition at line 1134 of file nnet-compile.cc.

References NnetComputation::commands, NetworkNode::component_index, Compiler::StepInfo::deriv, Nnet::GetComponent(), Nnet::GetNode(), KALDI_ASSERT, kaldi::nnet3::kBackprop, kaldi::nnet3::kBackpropNeedsInput, kaldi::nnet3::kBackpropNeedsOutput, kaldi::nnet3::kComponent, kaldi::nnet3::kUpdatableComponent, kaldi::nnet3::kUsesMemo, Compiler::nnet_, NetworkNode::node_type, Component::Properties(), Compiler::steps_, NetworkNode::u, and Compiler::StepInfo::value.

Referenced by Compiler::CompileBackward().

1135  {
1136  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1137  const StepInfo &step_info = steps_[step];
1138  int32 input_step = step - 1;
1139  const StepInfo &input_step_info = steps_[input_step];
1140  int32 node_index = step_info.node_index;
1141  const NetworkNode &node = nnet_.GetNode(node_index);
1142  KALDI_ASSERT(node.node_type == kComponent);
1143  int32 component_index = node.u.component_index;
1144  const Component *component = nnet_.GetComponent(component_index);
1145  int32 properties = component->Properties();
1146 
1147  int32 input_submatrix_index = input_step_info.value,
1148  output_submatrix_index = step_info.value,
1149  input_deriv_submatrix_index = input_step_info.deriv,
1150  output_deriv_submatrix_index = step_info.deriv,
1151  memo_index = (properties & kUsesMemo ? step : 0);
1152  KALDI_ASSERT(output_deriv_submatrix_index > 0 &&
1153  (input_deriv_submatrix_index > 0 ||
1154  properties & kUpdatableComponent));
1155 
1156  if (! (properties & kBackpropNeedsInput))
1157  input_submatrix_index = 0;
1158  if (! (properties & kBackpropNeedsOutput))
1159  output_submatrix_index = 0;
1160 
1161  NnetComputation::Command c(kBackprop,
1162  component_index,
1163  step_info.precomputed_indexes_index,
1164  input_submatrix_index,
1165  output_submatrix_index,
1166  output_deriv_submatrix_index,
1167  input_deriv_submatrix_index,
1168  memo_index);
1169  computation->commands.push_back(c);
1170 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
virtual int32 Properties() const =0
Return bitmask of the component's properties.
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddBackwardStepInput ( int32  step,
NnetComputation computation 
) const
private

Definition at line 1116 of file nnet-compile.cc.

References NnetComputation::commands, Nnet::GetNode(), NnetComputation::IsWholeMatrix(), KALDI_ASSERT, kaldi::nnet3::kComponent, kaldi::nnet3::kInput, kaldi::nnet3::kProvideOutput, Compiler::nnet_, and Compiler::steps_.

Referenced by Compiler::CompileBackward().

1117  {
1118  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1119  const StepInfo &step_info = steps_[step];
1120  int32 node_index = step_info.node_index,
1121  deriv_submatrix_index = step_info.deriv;
1122  if (deriv_submatrix_index == 0)
1123  return; // Nothing to do.
1124  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
1125  const NetworkNode &node = nnet_.GetNode(node_index);
1126  // actually, currently the node type would always be kInput.
1127  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
1128 
1129  NnetComputation::Command c(kProvideOutput, deriv_submatrix_index, node_index);
1130  computation->commands.push_back(c);
1131 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddCommands ( const std::vector< bool > &  deriv_needed,
const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

Definition at line 107 of file nnet-compile.cc.

References Compiler::AllocateMatrices(), NnetComputation::commands, Compiler::CompileBackward(), Compiler::CompileForward(), Compiler::DeallocateMatrices(), NnetComputation::GetWholeSubmatrices(), kaldi::nnet3::kNoOperationMarker, NnetComputation::matrices, NnetComputation::need_model_derivative, Compiler::requests_, Compiler::SetUpPrecomputedIndexes(), and Compiler::steps_.

Referenced by Compiler::CreateComputation().

109  {
110  computation->need_model_derivative = requests_[0]->need_model_derivative;
111  int32 arbitrary_factor = 8;
112  computation->commands.reserve(computation->matrices.size()
113  * arbitrary_factor);
114 
115  std::vector<int32> whole_submatrices;
116  computation->GetWholeSubmatrices(&whole_submatrices);
117  AllocateMatrices(whole_submatrices, computation);
118  SetUpPrecomputedIndexes(step_to_segment, computation);
119  int32 num_steps = steps_.size();
120  for (int32 step = 0; step < num_steps; step++) {
121  CompileForward(step, computation);
122  if (step + 1 < static_cast<int32>(step_to_segment.size()) &&
123  step_to_segment[step + 1] != step_to_segment[step]) {
124  // insert a marker that separates segments of the computation.
125  computation->commands.push_back(
126  NnetComputation::Command(kNoOperationMarker));
127  }
128  }
129 
130  // mark the end of the forward phase.
131  computation->commands.push_back(
132  NnetComputation::Command(kNoOperationMarker));
133 
134  for (int32 step = num_steps - 1; step >= 0; step--)
135  if (deriv_needed[step])
136  CompileBackward(step, computation);
137 
138  DeallocateMatrices(whole_submatrices, step_to_segment, computation);
139 }
void CompileBackward(int32 step, NnetComputation *computation)
void SetUpPrecomputedIndexes(const std::vector< int32 > &step_to_segment, NnetComputation *computation)
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
void DeallocateMatrices(const std::vector< int32 > &whole_submatrices, const std::vector< int32 > &step_to_segment, NnetComputation *computation)
void AllocateMatrices(const std::vector< int32 > &whole_submatrices, NnetComputation *computation) const
void CompileForward(int32 step, NnetComputation *computation) const
void AddForwardStepComponent ( int32  step,
NnetComputation computation 
) const
private

Definition at line 1082 of file nnet-compile.cc.

References NnetComputation::commands, NetworkNode::component_index, Nnet::GetComponent(), Nnet::GetNode(), KALDI_ASSERT, kaldi::nnet3::kComponent, kaldi::nnet3::kPropagate, kaldi::nnet3::kStoresStats, kaldi::nnet3::kUsesMemo, Compiler::nnet_, NetworkNode::node_type, Component::Properties(), Compiler::requests_, Compiler::steps_, NetworkNode::u, and Compiler::StepInfo::value.

Referenced by Compiler::CompileForward().

1083  {
1084  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1085  const StepInfo &step_info = steps_[step];
1086  int32 input_step = step - 1;
1087  const StepInfo &input_step_info = steps_[input_step];
1088  int32 node_index = step_info.node_index;
1089  const NetworkNode &node = nnet_.GetNode(node_index);
1090  KALDI_ASSERT(node.node_type == kComponent);
1091  int32 component_index = node.u.component_index;
1092  const Component *component = nnet_.GetComponent(component_index);
1093 
1094  // note RE memo_index: we'll renumber them in optimization to get rid of gaps.
1095  // The use of 'step' as the memo index is OK because step > 0 if we're doing
1096  // forward propagation, there must be preceding steps for inputs or for
1097  // component-input nodes).
1098  int32 properties = component->Properties(),
1099  input_submatrix_index = input_step_info.value,
1100  output_submatrix_index = step_info.value,
1101  memo_index = (step_info.deriv > 0 && (properties & kUsesMemo) ? step : 0),
1102  store_stats = (requests_[0]->store_component_stats &&
1103  (properties & kStoresStats) ? 1 : 0);
1104 
1105  NnetComputation::Command c(kPropagate,
1106  component_index,
1107  step_info.precomputed_indexes_index,
1108  input_submatrix_index,
1109  output_submatrix_index,
1110  memo_index,
1111  store_stats);
1112  computation->commands.push_back(c);
1113 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
virtual int32 Properties() const =0
Return bitmask of the component's properties.
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddForwardStepInput ( int32  step,
NnetComputation computation 
) const
private

Definition at line 1065 of file nnet-compile.cc.

References NnetComputation::commands, Nnet::GetNode(), NnetComputation::IsWholeMatrix(), kaldi::nnet3::kAcceptInput, KALDI_ASSERT, kaldi::nnet3::kComponent, kaldi::nnet3::kInput, Compiler::nnet_, and Compiler::steps_.

Referenced by Compiler::CompileForward().

1066  {
1067  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1068  const StepInfo &step_info = steps_[step];
1069  int32 node_index = step_info.node_index,
1070  submatrix_index = step_info.value;
1071  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
1072 
1073  const NetworkNode &node = nnet_.GetNode(node_index);
1074  // actually currently the node type would always be kInput.
1075  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
1076 
1077  NnetComputation::Command c(kAcceptInput, submatrix_index, node_index);
1078  computation->commands.push_back(c);
1079 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AllocateMatrices ( const std::vector< int32 > &  whole_submatrices,
NnetComputation computation 
) const
private

Definition at line 1174 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::StepInfo::deriv, Compiler::graph_, ComputationGraph::is_input, Nnet::IsOutputNode(), KALDI_ASSERT, kaldi::nnet3::kAllocMatrix, kaldi::nnet3::kSetConst, NnetComputation::matrices, Compiler::nnet_, Compiler::StepInfo::node_index, Compiler::StepInfo::output_cindex_ids, Compiler::steps_, NnetComputation::submatrices, and Compiler::StepInfo::value.

Referenced by Compiler::AddCommands().

1175  {
1176  KALDI_ASSERT(computation->commands.empty());
1177  // Work out which matrices are inputs to the computation (or output-derivs,
1178  // which are also supplied as inputs to the computation); we won't be setting
1179  // these up.
1180  unordered_set<int32> input_and_oderiv_matrices;
1181  int32 num_steps = steps_.size();
1182  for (int32 step = 0; step < num_steps; step++) {
1183  const StepInfo &this_info = steps_[step];
1184  if (this_info.output_cindex_ids.empty())
1185  continue;
1186  int32 first_cindex_id = this_info.output_cindex_ids.front(),
1187  node_index = this_info.node_index;
1188  bool is_input = graph_.is_input[first_cindex_id],
1189  is_output = nnet_.IsOutputNode(node_index);
1190  if (is_input) {
1191  int32 value_submatrix_index = this_info.value,
1192  value_matrix_index =
1193  computation->submatrices[value_submatrix_index].matrix_index;
1194  input_and_oderiv_matrices.insert(value_matrix_index);
1195  }
1196  if (is_output && this_info.deriv != 0) {
1197  int32 deriv_submatrix_index = this_info.deriv,
1198  deriv_matrix_index =
1199  computation->submatrices[deriv_submatrix_index].matrix_index;
1200  input_and_oderiv_matrices.insert(deriv_matrix_index);
1201  }
1202  }
1203 
1204  int32 num_matrices = computation->matrices.size();
1205  for (int32 m = 1; m < num_matrices; m++) {
1206  // We don't set up the matrices that are inputs to the computation;
1207  // this happens when the user provides the input.
1208  if (input_and_oderiv_matrices.count(m) == 0) {
1209  // get a submatrix index that refers to the entire matrix.
1210  int32 submatrix_index = whole_submatrices[m];
1211 
1212  computation->commands.push_back(
1213  NnetComputation::Command(kAllocMatrix, submatrix_index));
1214  // Later in the optimization phase, it turns out that zeroing is not
1215  // necessary for some matrices, we'll remove the redundant kSetConst
1216  // commands.
1217  computation->commands.push_back(
1218  NnetComputation::Command(0.0, kSetConst, submatrix_index));
1219  }
1220  }
1221 }
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
ComputationGraph graph_
Definition: nnet-compile.h:64
std::vector< bool > is_input
For each Cindex this tells us whether it was provided as an input to the network. ...
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileBackward ( int32  step,
NnetComputation computation 
)
private

Definition at line 1035 of file nnet-compile.cc.

References Compiler::AddBackwardStepComponent(), Compiler::AddBackwardStepInput(), NnetComputation::commands, Compiler::CompileBackwardDescriptor(), Nnet::GetNode(), Compiler::IsInputStep(), KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kComponent, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, kaldi::nnet3::kInput, kaldi::nnet3::kNoOperationPermanent, Compiler::nnet_, Compiler::StepInfo::node_index, NetworkNode::node_type, and Compiler::steps_.

Referenced by Compiler::AddCommands().

1036  {
1037  KALDI_ASSERT(step < static_cast<int32>(steps_.size()));
1038  const StepInfo &step_info = steps_[step];
1039  int32 node_index = step_info.node_index;
1040  const NetworkNode &node = nnet_.GetNode(node_index);
1041 
1042  switch (node.node_type) {
1043  case kInput:
1044  AddBackwardStepInput(step, computation);
1045  if (!IsInputStep(step + 1)) // Make sure backward computation is nonempty.
1046  computation->commands.push_back(
1047  NnetComputation::Command(kNoOperationPermanent));
1048  break;
1049  case kDimRange:
1050  break; // Nothing to do.
1051  case kComponent:
1052  AddBackwardStepComponent(step, computation);
1053  break;
1054  case kDescriptor:
1055  CompileBackwardDescriptor(step, computation);
1056  break;
1057  default:
1058  KALDI_ERR << "Invalid node type";
1059  }
1060 }
bool IsInputStep(int32 step) const
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
#define KALDI_ERR
Definition: kaldi-error.h:127
void CompileBackwardDescriptor(int32 step, NnetComputation *computation)
void AddBackwardStepInput(int32 step, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddBackwardStepComponent(int32 step, NnetComputation *computation) const
void CompileBackwardDescriptor ( int32  step,
NnetComputation computation 
)
private

Definition at line 1014 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::CompileBackwardSumDescriptor(), Compiler::StepInfo::deriv, Nnet::IsOutputNode(), NnetComputation::IsWholeMatrix(), kaldi::nnet3::kAcceptInput, KALDI_ASSERT, Compiler::nnet_, Compiler::StepInfo::node_index, Compiler::steps_, and Compiler::StepInfo::value_parts.

Referenced by Compiler::CompileBackward().

1015  {
1016  StepInfo &step_info = steps_[step];
1017  if (nnet_.IsOutputNode(step_info.node_index) &&
1018  step_info.deriv > 0) {
1019  int32 deriv_submatrix_index = step_info.deriv;
1020  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
1021  NnetComputation::Command c(kAcceptInput, deriv_submatrix_index,
1022  step_info.node_index);
1023  computation->commands.push_back(c);
1024  }
1025 
1026  // the top-level descriptor has a bunch of parts that we concatenate features
1027  // over.
1028  int32 num_parts = step_info.value_parts.size();
1029  for (int32 part = 0; part < num_parts; part++)
1030  CompileBackwardSumDescriptor(step, part,
1031  computation);
1032 }
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< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileBackwardSumDescriptor(int32 step, int32 part_index, NnetComputation *computation) const
void CompileBackwardFromIndexes ( int32  deriv_submatrix_index,
int32  input_deriv_submatrix_index,
BaseFloat  alpha,
const std::vector< int32 > &  indexes,
NnetComputation computation 
) const
private

Definition at line 924 of file nnet-compile.cc.

References NnetComputation::commands, kaldi::nnet3::HasContiguousProperty(), rnnlm::i, NnetComputation::indexes, NnetComputation::indexes_ranges, kaldi::nnet3::kAddRowRanges, kaldi::nnet3::kAddRows, KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kMatrixAdd, and NnetComputation::submatrices.

Referenced by Compiler::CompileBackwardFromSubmatLocations().

929  {
930 
931  int32 num_rows = computation->submatrices[deriv_submatrix_index].num_rows,
932  input_num_rows =
933  computation->submatrices[input_deriv_submatrix_index].num_rows;
934  KALDI_ASSERT(indexes.size() == num_rows);
935  if (input_num_rows == num_rows) {
936  int32 i;
937  for (i = 0; i < num_rows; i++)
938  if (indexes[i] != i)
939  break;
940  if (i == num_rows) { // Simplest case: just matrix addition.
941  computation->commands.push_back(
942  NnetComputation::Command(alpha,
943  kMatrixAdd,
944  input_deriv_submatrix_index,
945  deriv_submatrix_index));
946 
947  return;
948  }
949  }
950  if (input_num_rows >= num_rows) {
951  // If there are no repeated elements in the "indexes" array, we can reverse
952  // the mapping and make it an operation of type kAddRows. TODO: change this
953  // to use kAddToRows, kCopyToRows, when implemented (will be more
954  // efficient).
955  std::vector<int32> reverse_indexes(input_num_rows, -1);
956  int32 i;
957  for (i = 0; i < num_rows; i++) {
958  int32 index_i = indexes[i];
959  KALDI_ASSERT(index_i >= -1 && index_i < input_num_rows);
960  if (index_i >= 0) {
961  if (reverse_indexes[index_i] == -1)
962  reverse_indexes[index_i] = i;
963  else
964  break;
965  } // note: there may be -1's in 'indexes', meaning just use zero.
966  }
967  if (i == num_rows) {
968  // There were no repeated elements, and this strategy will work.
969  int32 indexes_index = computation->indexes.size();
970  computation->indexes.push_back(reverse_indexes);
971  computation->commands.push_back(
972  NnetComputation::Command(alpha,
973  kAddRows,
974  input_deriv_submatrix_index,
975  deriv_submatrix_index,
976  indexes_index));
977  return;
978  }
979  }
980  std::vector<std::pair<int32, int32> > ranges;
981  if (HasContiguousProperty(indexes, &ranges)) {
982  // the operation can be set up as AddRowRanges.
983  if (static_cast<int32>(ranges.size()) != input_num_rows) {
984  KALDI_ASSERT(static_cast<int32>(ranges.size()) < input_num_rows);
985  // extend with (-1, -1) pairs.
986  ranges.resize(input_num_rows, std::pair<int32,int32>(-1, -1));
987  }
988  int32 indexes_ranges_index = computation->indexes_ranges.size();
989  computation->indexes_ranges.push_back(ranges);
990  computation->commands.push_back(
991  NnetComputation::Command(alpha,
993  input_deriv_submatrix_index,
994  deriv_submatrix_index,
995  indexes_ranges_index));
996  // TODO: if any of these ranges are quite long (summing over many rows), the
997  // resulting code could be inefficient because the AddRowRanges kernels
998  // takes time linear in the length of the range. Using a temporary matrix
999  // with an intermediate size would make this more efficient in that case, so
1000  // the one command would be two commands (plus commands to set up and
1001  // destroy the temporary matrix).
1002  return;
1003  }
1004 
1005  // If you ever reach here, it means someone has used a type of network that we
1006  // don't yet support in the backprop. Basically this case can be handled by
1007  // creating a temporary matrix to reorder the matrix at deriv_submatrix_index,
1008  // (using CopyRows), and doing AddRowRanges from that.
1009  // It wouldn't be too much work.
1010  KALDI_ERR << "This case not implemented yet.";
1011 }
bool HasContiguousProperty(const std::vector< int32 > &indexes, std::vector< std::pair< int32, int32 > > *reverse_indexes)
This function returns true if for each integer i != -1, all the indexes j at which indexes[j] == i ar...
#define KALDI_ERR
Definition: kaldi-error.h:127
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileBackwardFromSubmatLocations ( int32  deriv_submatrix_index,
BaseFloat  alpha,
const std::vector< std::pair< int32, int32 > > &  submat_locations,
NnetComputation computation 
) const
private

Definition at line 872 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::CompileBackwardFromIndexes(), kaldi::nnet3::ConvertToIndexes(), NnetComputation::indexes_multi, kaldi::IsSortedAndUniq(), kaldi::nnet3::kAddToRowsMulti, and KALDI_ERR.

Referenced by Compiler::CompileBackwardFromSubmatLocationsList().

876  {
877  // This function creates a command to handle an individual piece of the
878  // Descriptor, for backprop. Note: because the backprop case is a little
879  // trickier to implement efficiently on the GPU, there may be cases
880  // which we will refuse to implement backprop for if we get here.
881 
882 
883 
884  int32 first_value;
885  std::vector<int32> second_values;
886  if (ConvertToIndexes(submat_locations, &first_value,
887  &second_values)) {
888  int32 input_deriv_submatrix_index = first_value;
889  CompileBackwardFromIndexes(deriv_submatrix_index,
890  input_deriv_submatrix_index,
891  alpha,
892  second_values,
893  computation);
894  return;
895  } else {
896  // There are multiple source matrices.
897  std::vector<std::pair<int32, int32> > submat_locations_sorted;
898  std::sort(submat_locations_sorted.begin(), submat_locations_sorted.end());
899  if (IsSortedAndUniq(submat_locations_sorted)) {
900  // There are no repeats in any of the submat locations. This means that
901  // we can just use kAddToRowsMulti (i.e. AddToRows with pointer
902  // destination). If there were repeats, the CUDA kernel would require
903  // special synchronization so we don't allow it.
904  int32 indexes_multi_index = computation->indexes_multi.size();
905  computation->indexes_multi.push_back(submat_locations);
906  computation->commands.push_back(
907  NnetComputation::Command(alpha,
909  deriv_submatrix_index,
910  indexes_multi_index));
911  return;
912  }
913  // If you reach this point, there is a case that wasn't handled. Our
914  // intended strategy to handle it, if it's ever needed, is to create a
915  // temporary matrix consisting of all the unique submat_locations in the
916  // input. We would first recurse to CompileBackwardFromIndexes, and
917  // let it write to this temporary matrix; and then do the kAddToRowsMulti
918  // command as above to go from the temporary matrix to the multiple
919  // matrices.
920  KALDI_ERR << "This case not handled.";
921  }
922 }
bool ConvertToIndexes(const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -...
void CompileBackwardFromIndexes(int32 deriv_submatrix_index, int32 input_deriv_submatrix_index, BaseFloat alpha, const std::vector< int32 > &indexes, NnetComputation *computation) const
#define KALDI_ERR
Definition: kaldi-error.h:127
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
void CompileBackwardFromSubmatLocationsList ( int32  deriv_submatrix_index,
BaseFloat  alpha,
const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_locations,
NnetComputation computation 
) const
private

Definition at line 803 of file nnet-compile.cc.

References Compiler::CompileBackwardFromSubmatLocations(), rnnlm::i, and kaldi::nnet3::SplitLocationsBackward().

Referenced by Compiler::CompileBackwardSumDescriptor().

807  {
808  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
809  SplitLocationsBackward(submat_lists, &split_lists);
810  int32 size = split_lists.size(); // size may be zero e.g. for unused outputs.
811  for (int32 i = 0; i < size; i++)
813  deriv_submatrix_index,
814  alpha,
815  split_lists[i],
816  computation);
817 }
void CompileBackwardFromSubmatLocations(int32 deriv_submatrix_index, BaseFloat alpha, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
void SplitLocationsBackward(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
This function has the same interface as SplitLocations(); however, it ensures certain additional prop...
void CompileBackwardSumDescriptor ( int32  step,
int32  part_index,
NnetComputation computation 
) const
private

Definition at line 820 of file nnet-compile.cc.

References Compiler::CompileBackwardFromSubmatLocationsList(), Compiler::ComputeDerivSubmatLocationsList(), Compiler::StepInfo::deriv_parts, NetworkNode::descriptor, Nnet::GetNode(), rnnlm::i, Compiler::StepInfo::input_locations_list, KALDI_ASSERT, Compiler::nnet_, Compiler::StepInfo::node_index, Descriptor::Part(), Compiler::SplitByScale(), and Compiler::steps_.

Referenced by Compiler::CompileBackwardDescriptor().

821  {
822  const StepInfo &step_info = steps_[step];
823  int32 deriv_submatrix_index = step_info.deriv_parts[part_index];
824  KALDI_ASSERT(deriv_submatrix_index > 0); // or should not have called this.
825  const SumDescriptor &descriptor =
826  nnet_.GetNode(step_info.node_index).descriptor.Part(part_index);
827  // Note: `offset_term` appeared in the forward computation here but does not
828  // come into the backward computation.
829 
830  // `input_locations_list` is a vector indexed by row-index, with each element
831  // being a list of pairs (step, row_index) representing terms in a weighted
832  // sum.
833  const std::vector<std::vector<std::pair<int32,int32> > >
834  &input_locations_list = step_info.input_locations_list[part_index];
835 
836  // `split_locations_lists` is a vector of pairs `(alpha, locations_list)`
837  // where alpha is the scale in which these items appear in the
838  // summation and `locations_list` is the same format as `input_locations_list`
839  std::vector<std::pair<BaseFloat,
840  std::vector<std::vector<std::pair<int32,int32> > > > > split_locations_lists;
841  BaseFloat shared_alpha = SplitByScale(descriptor, input_locations_list,
842  &split_locations_lists);
843  if (shared_alpha - shared_alpha == 0.0) {
844  // If the returned value 'shared_alpha' is finite, this indicates that there
845  // was no need to split up 'input_locations_list' because all the alpha
846  // values (scales) were the same. We treat this case specially for
847  // efficiency reasons; this branch will be the most common branch.
848  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
849  ComputeDerivSubmatLocationsList(input_locations_list,
850  &submat_locations_list);
851  CompileBackwardFromSubmatLocationsList(deriv_submatrix_index,
852  shared_alpha,
853  submat_locations_list,
854  computation);
855  } else {
856  for (size_t i = 0; i < split_locations_lists.size(); i++) {
857  BaseFloat this_alpha = split_locations_lists[i].first;
858  KALDI_ASSERT(this_alpha - this_alpha == 0.0);
859  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
860  ComputeDerivSubmatLocationsList(split_locations_lists[i].second,
861  &submat_locations_list);
862  CompileBackwardFromSubmatLocationsList(deriv_submatrix_index,
863  this_alpha,
864  submat_locations_list,
865  computation);
866  }
867  }
868 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
float BaseFloat
Definition: kaldi-types.h:29
void CompileBackwardFromSubmatLocationsList(int32 deriv_submatrix_index, BaseFloat alpha, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
const SumDescriptor & Part(int32 n) const
returns the n'th part.
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ComputeDerivSubmatLocationsList(const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
BaseFloat SplitByScale(const SumDescriptor &descriptor, const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::pair< BaseFloat, std::vector< std::vector< std::pair< int32, int32 > > > > > *split_locations_lists) const
This function helps to handle scalar factors in Descriptors (expressions like `Scale(-1.0,
void CompileForward ( int32  step,
NnetComputation computation 
) const
private

Definition at line 391 of file nnet-compile.cc.

References Compiler::AddForwardStepComponent(), Compiler::AddForwardStepInput(), NnetComputation::commands, Compiler::CompileForwardDescriptor(), Nnet::GetNode(), Compiler::IsInputStep(), KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kComponent, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, kaldi::nnet3::kInput, kaldi::nnet3::kNoOperationPermanent, Compiler::nnet_, Compiler::StepInfo::node_index, NetworkNode::node_type, and Compiler::steps_.

Referenced by Compiler::AddCommands().

392  {
393  KALDI_ASSERT(step < static_cast<int32>(steps_.size()));
394  const StepInfo &step_info = steps_[step];
395  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
396  switch (node.node_type) {
397  case kInput: // Note: input nodes appear before other node types.
398  AddForwardStepInput(step, computation);
399  if (!IsInputStep(step + 1)) // Make sure forward computation is nonempty.
400  computation->commands.push_back(
401  NnetComputation::Command(kNoOperationPermanent));
402  break;
403  case kDimRange: break; // Nothing to do.
404  case kComponent:
405  AddForwardStepComponent(step, computation);
406  break;
407  case kDescriptor:
408  CompileForwardDescriptor(step, computation);
409  break;
410  default:
411  KALDI_ERR << "Invalid node type";
412  }
413 
414 }
bool IsInputStep(int32 step) const
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
void AddForwardStepComponent(int32 step, NnetComputation *computation) const
#define KALDI_ERR
Definition: kaldi-error.h:127
void AddForwardStepInput(int32 step, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileForwardDescriptor(int32 step, NnetComputation *computation) const
void CompileForwardDescriptor ( int32  step,
NnetComputation computation 
) const
private

Definition at line 417 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::CompileForwardSumDescriptor(), Nnet::IsOutputNode(), NnetComputation::IsWholeMatrix(), KALDI_ASSERT, kaldi::nnet3::kProvideOutput, Compiler::nnet_, Compiler::StepInfo::node_index, Compiler::steps_, and Compiler::StepInfo::value.

Referenced by Compiler::CompileForward().

418  {
419  int32 num_parts = steps_[step].value_parts.size();
420  for (int32 part = 0; part < num_parts; part++)
421  CompileForwardSumDescriptor(step, part, computation);
422  const StepInfo &step_info = steps_[step];
423  if (nnet_.IsOutputNode(step_info.node_index)) {
424  // If the node is an output then we need to add commands to provide the
425  // output to the user, and possibly to get derivatives w.r.t. the output
426  // from the user.
427  int32 node_index = step_info.node_index,
428  submatrix_index = step_info.value;
429  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
430  NnetComputation::Command c(kProvideOutput, submatrix_index, node_index);
431  computation->commands.push_back(c);
432  }
433 }
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
void CompileForwardSumDescriptor(int32 step, int32 part_index, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileForwardFromIndexes ( int32  value_submatrix_index,
int32  input_submatrix_index,
BaseFloat  alpha,
const std::vector< int32 > &  indexes,
NnetComputation computation 
) const
private

Adds to `computation` a command that adds to the submatrix in `value_submatrix_index` a quantity consisting of alpha times the submatrix in `input_submatrix_index`, with a row mapping given by `indexes`.

Definition at line 723 of file nnet-compile.cc.

References NnetComputation::commands, rnnlm::i, NnetComputation::indexes, kaldi::nnet3::kAddRows, kaldi::nnet3::kMatrixAdd, and NnetComputation::submatrices.

Referenced by Compiler::CompileForwardFromSubmatLocations().

728  {
729 
730  int32 input_num_rows =
731  computation->submatrices[input_submatrix_index].num_rows,
732  num_rows = indexes.size();
733  if (input_num_rows == num_rows) {
734  int32 i;
735  for (i = 0; i < num_rows; i++)
736  if (indexes[i] != i)
737  break;
738  if (i == num_rows) { // Simplest case: just matrix addition.
739  computation->commands.push_back(
740  NnetComputation::Command(alpha, kMatrixAdd,
741  value_submatrix_index,
742  input_submatrix_index));
743 
744  return;
745  }
746  }
747  // if we got to here, it's not just a case of matrix-copy or matrix-add,
748  // but it's still from a single source matrix.
749  int32 indexes_index = computation->indexes.size();
750  computation->indexes.push_back(indexes);
751  computation->commands.push_back(
752  NnetComputation::Command(alpha, kAddRows, value_submatrix_index,
753  input_submatrix_index, indexes_index));
754  return;
755 }
void CompileForwardFromSubmatLocations ( int32  value_submatrix_index,
BaseFloat  alpha,
const std::vector< std::pair< int32, int32 > > &  submat_locations,
NnetComputation computation 
) const
private

Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor.

This is called from CompileForwardFromSubmatLocationsList.

Parameters
[in]value_submatrix_indexThe submatrix index of the quanitity we are computing (part of a Descriptor; it's something like Sum(tdnn1, tdnn2) in general).
[in]alphaThe scale (1.0 unless Scale(...) expressions are involved in descriptors) with which these terms are present in the summation.
[in]submat_locationsIndexed by the row index corresponding to the rows of the submatrix referred to by 'value_submatrix_index', this reprenents the source vector which we are adding to this row, in the format (submatrix-index, row-index), or (-1, -1) if in this case there is nothing to add.
[in,out]computationThe computation which we are adding commands to.

Definition at line 757 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::CompileForwardFromIndexes(), kaldi::nnet3::ConvertToIndexes(), NnetComputation::indexes_multi, and kaldi::nnet3::kAddRowsMulti.

Referenced by Compiler::CompileForwardFromSubmatLocationsList().

761  {
762 
763  int32 input_submatrix_index = -1;
764  std::vector<int32> indexes;
765  if (ConvertToIndexes(submat_locations, &input_submatrix_index, &indexes)) {
766  CompileForwardFromIndexes(value_submatrix_index,
767  input_submatrix_index,
768  alpha,
769  indexes,
770  computation);
771  return;
772  } else {
773  // There are multiple source matrices.
774  int32 indexes_multi_index = computation->indexes_multi.size();
775  computation->indexes_multi.push_back(submat_locations);
776  computation->commands.push_back(
777  NnetComputation::Command(alpha, kAddRowsMulti,
778  value_submatrix_index,
779  indexes_multi_index));
780  return;
781  }
782 }
bool ConvertToIndexes(const std::vector< std::pair< int32, int32 > > &location_vector, int32 *first_value, std::vector< int32 > *second_values)
If it is the case for some i >= 0 that all the .first elements of "location_vector" are either i or -...
void CompileForwardFromIndexes(int32 value_submatrix_index, int32 input_submatrix_index, BaseFloat alpha, const std::vector< int32 > &indexes, NnetComputation *computation) const
Adds to `computation` a command that adds to the submatrix in `value_submatrix_index` a quantity cons...
void CompileForwardFromSubmatLocationsList ( int32  value_submatrix_index,
BaseFloat  alpha,
const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_locations,
NnetComputation computation 
) const
private

Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor.

This is called from CompileForwardSumDescriptor.

Parameters
[in]value_submatrix_indexThe submatrix index of the quanitity we are computing (part of a Descriptor; it's something like Sum(tdnn1, tdnn2) in general).
[in]alphaThe scale (1.0 unless Scale(...) expressions are involved in descriptors) with which these terms are present in the summation.
[in]submat_locationsIndexed by the row index of the submatrix referred to by 'value_submatrix_index', each element is a list of sources over which we must sum to obtain that row. Each source is a pair (submatrix-index, row-index).

Definition at line 784 of file nnet-compile.cc.

References Compiler::CompileForwardFromSubmatLocations(), rnnlm::i, and kaldi::nnet3::SplitLocations().

Referenced by Compiler::CompileForwardSumDescriptor().

788  {
789  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
790  SplitLocations(submat_lists, &split_lists);
791  int32 size = split_lists.size();
792  // note: `size` may be empty in unusual cases so don't assert that it's
793  // nonzero.
794  for (int32 i = 0; i < size; i++)
796  value_submatrix_index,
797  alpha,
798  split_lists[i],
799  computation);
800 }
void SplitLocations(const std::vector< std::vector< std::pair< int32, int32 > > > &submat_lists, std::vector< std::vector< std::pair< int32, int32 > > > *split_lists)
The input to this function is a vector of lists of pairs, and this function splits it up into a list ...
void CompileForwardFromSubmatLocations(int32 value_submatrix_index, BaseFloat alpha, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor...
void CompileForwardSumDescriptor ( int32  step,
int32  part_index,
NnetComputation computation 
) const
private

Definition at line 661 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::CompileForwardFromSubmatLocationsList(), Compiler::ComputeValueSubmatLocationsList(), NetworkNode::descriptor, Nnet::GetNode(), SumDescriptor::GetScaleForNode(), rnnlm::i, Compiler::StepInfo::input_locations_list, KALDI_ASSERT, kaldi::nnet3::kSetConst, Compiler::nnet_, Compiler::StepInfo::node_index, Descriptor::Part(), Compiler::SplitByScale(), Compiler::steps_, and Compiler::StepInfo::value_parts.

Referenced by Compiler::CompileForwardDescriptor().

662  {
663  const StepInfo &step_info = steps_[step];
664  int32 value_submatrix_index = step_info.value_parts[part_index];
665  const SumDescriptor &descriptor =
666  nnet_.GetNode(step_info.node_index).descriptor.Part(part_index);
667 
668  BaseFloat offset_term = descriptor.GetScaleForNode(-1);
669  if (offset_term != 0.0) {
670  computation->commands.push_back(
671  NnetComputation::Command(offset_term, kSetConst,
672  value_submatrix_index));
673  // if offset_term == 0.0 there's no need to do this, because
674  // we zeroed the matrix when we allocated it; search in this
675  // file for kSetConst to see the code. If we are redundantly
676  // setting the value, this will later be optimized out (in the
677  // common cases).
678  }
679 
680 
681  // `input_locations_list` is a vector indexed by row-index, with each element
682  // being a list of pairs (step, row_index) representing terms in a weighted
683  // sum.
684  const std::vector<std::vector<std::pair<int32,int32> > >
685  &input_locations_list = step_info.input_locations_list[part_index];
686 
687  // `split_locations_lists` is a vector of pairs `(alpha, locations_list)`
688  // where alpha is the scale in which these items appear in the
689  // summation and `locations_list` is the same format as `input_locations_list`
690  std::vector<std::pair<BaseFloat,
691  std::vector<std::vector<std::pair<int32,int32> > > > > split_locations_lists;
692  BaseFloat shared_alpha = SplitByScale(descriptor, input_locations_list,
693  &split_locations_lists);
694  if (shared_alpha - shared_alpha == 0.0) {
695  // If the returned value 'shared_alpha' is finite, this indicates that there was no
696  // need to split up 'input_locations_list' because all the alpha values
697  // (scales) were the same. We treat this case specially for efficiency
698  // reasons; this branch will be the most common branch.
699  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
700  ComputeValueSubmatLocationsList(input_locations_list,
701  &submat_locations_list);
703  value_submatrix_index,
704  shared_alpha,
705  submat_locations_list,
706  computation);
707  } else {
708  for (size_t i = 0; i < split_locations_lists.size(); i++) {
709  BaseFloat this_alpha = split_locations_lists[i].first;
710  KALDI_ASSERT(this_alpha - this_alpha == 0.0);
711  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
712  ComputeValueSubmatLocationsList(split_locations_lists[i].second,
713  &submat_locations_list);
715  value_submatrix_index,
716  this_alpha,
717  submat_locations_list,
718  computation);
719  }
720  }
721 }
void CompileForwardFromSubmatLocationsList(int32 value_submatrix_index, BaseFloat alpha, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
Adds to 'computation' commands for part of the forward computation corresponding to a Descriptor...
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
float BaseFloat
Definition: kaldi-types.h:29
const SumDescriptor & Part(int32 n) const
returns the n'th part.
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void ComputeValueSubmatLocationsList(const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
BaseFloat SplitByScale(const SumDescriptor &descriptor, const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::pair< BaseFloat, std::vector< std::vector< std::pair< int32, int32 > > > > > *split_locations_lists) const
This function helps to handle scalar factors in Descriptors (expressions like `Scale(-1.0,
void ComputeDerivNeeded ( const std::vector< std::vector< int32 > > &  steps,
const std::vector< int32 > &  step_to_segment,
std::vector< bool > *  deriv_needed 
)
private

Definition at line 176 of file nnet-compile.cc.

References ComputationGraph::cindexes, NetworkNode::component_index, Compiler::ComputeStepDependencies(), Nnet::GetComponent(), Nnet::GetNode(), Nnet::GetNodeNames(), kaldi::GetVerboseLevel(), Compiler::graph_, rnnlm::i, ComputationRequest::IndexForInput(), ComputationRequest::IndexForOutput(), ComputationRequest::inputs, ComputationGraph::is_input, Nnet::IsComponentNode(), Nnet::IsOutputNode(), KALDI_ASSERT, KALDI_VLOG, kaldi::nnet3::kUpdatableComponent, UpdatableComponent::LearningRate(), ComputationRequest::need_model_derivative, Compiler::nnet_, ComputationRequest::outputs, Component::Properties(), Compiler::requests_, and NetworkNode::u.

Referenced by Compiler::CreateComputation().

179  {
180  KALDI_ASSERT(steps.size() == step_to_segment.size() &&
181  step_to_segment[0] == 0 &&
182  step_to_segment.back() + 1 == requests_.size());
183  deriv_needed->clear();
184  int32 num_steps = steps.size();
185  deriv_needed->resize(num_steps, false);
186 
187  for (int32 step = 0; step < num_steps; step++) {
188  const std::vector<int32> &this_step = steps[step];
189  if (this_step.empty()) // empty steps are theoretically possible, e.g.
190  continue; // if a non-simple Component requires no input.
191  int32 cindex_id = this_step[0];
192  int32 node_index = graph_.cindexes[cindex_id].first;
193  bool is_input = graph_.is_input[cindex_id];
194 
195  std::string node_name = nnet_.GetNodeNames()[node_index];
196  unordered_set<int32> input_steps;
197  ComputeStepDependencies(this_step, step, &input_steps);
198 
199  unordered_set<int32>::iterator iter = input_steps.begin(),
200  end = input_steps.end();
201  // if some step that we depend on needs a derivative, we need the derivative.
202  for (; iter != end; ++iter) {
203  int32 dep_step = *iter;
204  KALDI_ASSERT(dep_step < step);
205  if ((*deriv_needed)[dep_step])
206  (*deriv_needed)[step] = true;
207  }
208  // if this step is an input and the user requested the derivative w.r.t. that
209  // input, we need the derivative.
210  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
211 
212  if (is_input) {
213  int32 input_index = request.IndexForInput(node_name);
214  KALDI_ASSERT(input_index != -1);
215  if (request.inputs[input_index].has_deriv)
216  (*deriv_needed)[step] = true;
217  }
218  // if this step is an output and the user is providing the derivative w.r.t. that
219  // output, we need a place to store the derivative, so we set (*deriv_needed) to
220  // true.
221  if (nnet_.IsOutputNode(node_index)) {
222  int32 output_index = request.IndexForOutput(node_name);
223  KALDI_ASSERT(output_index != -1);
224  if (request.outputs[output_index].has_deriv)
225  (*deriv_needed)[step] = true;
226  }
227 
228  // If this is an updatable Component node with a nonzero learning rate and
229  // the user requested model derivatives (e.g. during training), we need this
230  // step's derivative.
231  if (nnet_.IsComponentNode(node_index) && request.need_model_derivative) {
232  const NetworkNode &node = nnet_.GetNode(node_index);
233  const Component *c = nnet_.GetComponent(node.u.component_index);
234  if (c->Properties() & kUpdatableComponent) {
235  const UpdatableComponent *u = dynamic_cast<const UpdatableComponent*>(c);
236  KALDI_ASSERT(u != NULL);
237  if (u->LearningRate() != 0)
238  (*deriv_needed)[step] = true;
239  }
240  }
241  }
242  if (GetVerboseLevel() >= 5) {
243  std::ostringstream os;
244  os << "deriv_needed = ";
245  for (int32 i = 0; i < deriv_needed->size(); i++)
246  os << ((*deriv_needed)[i] ? "t" : "f");
247  os << "\n";
248  KALDI_VLOG(5) << os.str();
249  }
250 }
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
int32 GetVerboseLevel()
Definition: kaldi-error.h:69
const std::vector< std::string > & GetNodeNames() const
returns vector of node names (needed by some parsing code, for instance).
Definition: nnet-nnet.cc:63
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
ComputationGraph graph_
Definition: nnet-compile.h:64
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
bool IsComponentNode(int32 node) const
Returns true if this is a component node, meaning that it is of type kComponent.
Definition: nnet-nnet.cc:132
std::vector< bool > is_input
For each Cindex this tells us whether it was provided as an input to the network. ...
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
#define KALDI_VLOG(v)
Definition: kaldi-error.h:136
void ComputeStepDependencies(const std::vector< int32 > &this_step, int32 step_index, unordered_set< int32 > *dep_steps)
void ComputeDerivSubmatLocationsList ( const std::vector< std::vector< std::pair< int32, int32 > > > &  input_locations_list,
std::vector< std::vector< std::pair< int32, int32 > > > *  submat_locations_list 
) const
private

Definition at line 516 of file nnet-compile.cc.

References rnnlm::i, and Compiler::steps_.

Referenced by Compiler::CompileBackwardSumDescriptor().

519  {
520  submat_locations_list->clear();
521  submat_locations_list->resize(input_locations_list.size());
522  int32 size = submat_locations_list->size();
523  for (int32 i = 0; i < size; i++) {
524  const std::vector<std::pair<int32, int32> > &this_list = input_locations_list[i];
525  std::vector<std::pair<int32, int32> > &this_submat_list = (*submat_locations_list)[i];
526  this_submat_list.reserve(this_list.size());
527  std::vector<std::pair<int32, int32> >::const_iterator
528  input_iter = this_list.begin(), input_end = this_list.end();
529  for (; input_iter != input_end; ++input_iter) {
530  int32 step = input_iter->first,
531  deriv_submat_index = steps_[step].deriv,
532  row = input_iter->second;
533  if (deriv_submat_index > 0)
534  this_submat_list.push_back(std::pair<int32,int32>(deriv_submat_index,
535  row));
536  }
537  }
538 }
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void ComputeInputLocationsList ( int32  step,
int32  part_index,
std::vector< std::vector< std::pair< int32, int32 > > > *  input_locations 
) const
private

Definition at line 442 of file nnet-compile.cc.

References Compiler::cindex_id_to_location_, NetworkNode::descriptor, ComputationGraph::GetCindexId(), Nnet::GetNode(), Compiler::graph_, rnnlm::i, SumDescriptor::IsComputable(), rnnlm::j, KALDI_ASSERT, kaldi::nnet3::kNoTime, Compiler::nnet_, Descriptor::Part(), Compiler::steps_, and Index::t.

Referenced by Compiler::CreateStepInfo().

445  {
446 
447  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
448  const StepInfo &step_info = steps_[step];
449  const std::vector<Index> &output_indexes = step_info.output_indexes;
450  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
451  const SumDescriptor &descriptor = node.descriptor.Part(part_index);
452  int32 num_indexes = output_indexes.size();
453  submat_locations_list->clear();
454  submat_locations_list->resize(num_indexes);
455 
456  for (int32 i = 0; i < num_indexes; i++) {
457  const Index &index = output_indexes[i];
458  std::vector<std::pair<int32, int32> > &this_locations_list =
459  (*submat_locations_list)[i];
460  if (index.t != kNoTime) {
461  // a real Index, not a 'blank' one
462  // ('blank' indexes are inserted by some non-simple Components to
463  // satisfy internal constraints.
464  std::vector<int32> input_cindex_ids;
465  std::vector<Cindex> input_cindexes;
466  CindexSet cindex_set(graph_);
467  bool ans = descriptor.IsComputable(index, cindex_set, &input_cindexes);
468  // earlier compilation stages should have checked that it is computable,
469  // and the graph should still contain required inputs.
470  KALDI_ASSERT(ans);
471  std::sort(input_cindexes.begin(), input_cindexes.end());
472  int32 size = input_cindexes.size();
473  input_cindex_ids.resize(size);
474  for (int32 j = 0; j < size; j++) {
475  int32 c = graph_.GetCindexId(input_cindexes[j]);
476  KALDI_ASSERT(c != -1);
477  input_cindex_ids[j] = c;
478  }
479  this_locations_list.resize(size);
480  for (int32 j = 0; j < size; j++)
481  this_locations_list[j] = cindex_id_to_location_[input_cindex_ids[j]];
482  } else {
483  this_locations_list.clear();
484  }
485  }
486 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
ComputationGraph graph_
Definition: nnet-compile.h:64
int32 GetCindexId(const Cindex &cindex, bool is_input, bool *is_new)
Maps a Cindex to an integer cindex_id.
const SumDescriptor & Part(int32 n) const
returns the n'th part.
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
std::vector< std::pair< int32, int32 > > cindex_id_to_location_
This maps each cindex_id to its location.
Definition: nnet-compile.h:159
const int kNoTime
Definition: nnet-common.cc:568
void ComputeStepDependencies ( const std::vector< int32 > &  this_step,
int32  step_index,
unordered_set< int32 > *  dep_steps 
)
private

Definition at line 142 of file nnet-compile.cc.

References Compiler::cindex_id_to_location_, ComputationGraph::cindexes, ComputationGraph::dependencies, Compiler::graph_, Nnet::IsComponentNode(), KALDI_ASSERT, and Compiler::nnet_.

Referenced by Compiler::ComputeDerivNeeded().

145  {
146  dep_steps->clear();
147  if (this_step.empty())
148  return;
149  // steps always have a single node index, we can pick the first.
150  int32 node_index = graph_.cindexes[this_step[0]].first;
151  if (nnet_.IsComponentNode(node_index)) {
152  // there is only one step that a component step depends on, and it's the
153  // immediately preceding step (the component-input step).
154  KALDI_ASSERT(step_index > 0);
155  dep_steps->insert(step_index - 1);
156  return;
157  }
158  std::vector<int32>::const_iterator step_iter = this_step.begin(),
159  step_end = this_step.end();
160  int32 prev_input_step = -1; // this is an optimization for speed.
161  for (; step_iter != step_end; ++step_iter) {
162  int32 cindex_id = *step_iter;
163  const std::vector<int32> &dep = graph_.dependencies[cindex_id];
164  std::vector<int32>::const_iterator iter = dep.begin(), end = dep.end();
165  for (; iter != end; ++iter) {
166  int32 dep_cindex_id = *iter,
167  input_step = cindex_id_to_location_[dep_cindex_id].first;
168  if (input_step != prev_input_step) { // optimization.
169  prev_input_step = input_step;
170  dep_steps->insert(input_step);
171  }
172  }
173  }
174 }
ComputationGraph graph_
Definition: nnet-compile.h:64
std::vector< Cindex > cindexes
The mapping of cindex_id to Cindex.
bool IsComponentNode(int32 node) const
Returns true if this is a component node, meaning that it is of type kComponent.
Definition: nnet-nnet.cc:132
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:169
std::vector< std::pair< int32, int32 > > cindex_id_to_location_
This maps each cindex_id to its location.
Definition: nnet-compile.h:159
void ComputeValueSubmatLocationsList ( const std::vector< std::vector< std::pair< int32, int32 > > > &  input_locations_list,
std::vector< std::vector< std::pair< int32, int32 > > > *  submat_locations_list 
) const
private

Definition at line 488 of file nnet-compile.cc.

References rnnlm::i, and Compiler::steps_.

Referenced by Compiler::CompileForwardSumDescriptor().

491  {
492  submat_locations_list->clear();
493  submat_locations_list->resize(input_locations_list.size());
494  int32 size = submat_locations_list->size();
495  for (int32 i = 0; i < size; i++) {
496  const std::vector<std::pair<int32, int32> > &this_list =
497  input_locations_list[i];
498  std::vector<std::pair<int32, int32> > &this_submat_list =
499  (*submat_locations_list)[i];
500  this_submat_list.resize(this_list.size());
501  std::vector<std::pair<int32, int32> >::const_iterator
502  input_iter = this_list.begin(), input_end = this_list.end();
503  std::vector<std::pair<int32, int32> >::iterator iter =
504  this_submat_list.begin();
505  for (; input_iter != input_end; ++input_iter, ++iter) {
506  int32 step = input_iter->first,
507  value_submat_index = steps_[step].value,
508  row = input_iter->second;
509  iter->first = value_submat_index;
510  iter->second = row;
511  }
512  }
513 }
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void CreateComputation ( const CompilerOptions opts,
NnetComputation computation 
)

Definition at line 50 of file nnet-compile.cc.

References Compiler::AddCommands(), ComputationGraphBuilder::AllOutputsAreComputable(), ComputationStepsComputer::Check(), Compiler::cindex_id_to_location_, NnetComputation::Clear(), ComputationGraphBuilder::Compute(), kaldi::nnet3::ComputeComputationPhases(), Compiler::ComputeDerivNeeded(), ComputationStepsComputer::ComputeForSegment(), kaldi::nnet3::ConsolidateIoOperations(), Compiler::CreateStepInfo(), ComputationGraphBuilder::ExplainWhyAllOutputsNotComputable(), Compiler::graph_, KALDI_ERR, Compiler::nnet_, CompilerOptions::output_debug_info, Compiler::OutputDebugInfo(), ComputationGraphBuilder::Prune(), and Compiler::requests_.

Referenced by kaldi::nnet3::CompileLoopedInternal(), CachingOptimizingCompiler::CompileNoShortcut(), kaldi::nnet3::UnitTestNnetAnalyze(), kaldi::nnet3::UnitTestNnetCompile(), kaldi::nnet3::UnitTestNnetCompute(), and kaldi::nnet3::UnitTestNnetOptimizeWithOptions().

51  {
52  computation->Clear();
53  ComputationGraphBuilder builder(nnet_, &graph_);
54  // note: there are only >1 segments in a 'looped' computation.
55  for (size_t segment = 0; segment < requests_.size(); segment++) {
56  builder.Compute(*(requests_[segment]));
57  if (!builder.AllOutputsAreComputable()) {
58  builder.ExplainWhyAllOutputsNotComputable(); // prints logging info
59  KALDI_ERR << "Not all outputs were computable, cannot create computation.";
60  }
61  builder.Prune();
62  }
63  // see function declaration's comment for more on the meaning of "phases" (a
64  // phase will later be decomposed into one or more steps). for each segment
65  // s, phases_per_segment[s] is a list of phases; each phase is a list of
66  // cindex_ids.
67  std::vector<std::vector<std::vector<int32> > > phases_per_segment;
68  ComputeComputationPhases(nnet_, graph_, &phases_per_segment);
69  std::vector<std::vector<int32> > steps;
70  steps.reserve(1000);
71 
72  // maps each step to the segment in which it appears. in the normal case
73  // (non-looped computation), a vector of all zeros.
74  std::vector<int32> step_to_segment;
75 
76 
77  {
78  // note: this class will output to 'steps' and to 'cindex_id_to_location_'.
79  // it may incidentally change 'graph_' by adding a few cindexes.
80  ComputationStepsComputer steps_computer(nnet_, &graph_, &steps,
82 
83  for (size_t segment = 0; segment < requests_.size(); segment++) {
84  steps_computer.ComputeForSegment(*(requests_[segment]),
85  phases_per_segment[segment]);
86  while (step_to_segment.size() < steps.size())
87  step_to_segment.push_back(segment);
88 
89  // save memory, by deleting the phases we just consumed. the
90  // following two lines just exist to save memory.
91  std::vector<std::vector<int32> > temp;
92  phases_per_segment[segment].swap(temp);
93  }
94  steps_computer.Check();
95  }
96  std::vector<bool> deriv_needed;
97  ComputeDerivNeeded(steps, step_to_segment, &deriv_needed);
98  CreateStepInfo(deriv_needed, step_to_segment, &steps, computation);
99  AddCommands(deriv_needed, step_to_segment, computation);
100  // the following command reorders commands so kAcceptInput and kProvideOutput
101  // appear in the desired places.
102  ConsolidateIoOperations(nnet_, computation);
103  if (opts.output_debug_info)
104  OutputDebugInfo(computation);
105 }
void ConsolidateIoOperations(const Nnet &nnet, NnetComputation *computation)
This optimization puts the input operations (kAcceptInput) and output operations (kProvideOutput) at ...
void CreateStepInfo(const std::vector< bool > &deriv_needed, const std::vector< int32 > &step_to_segment, std::vector< std::vector< int32 > > *by_step, NnetComputation *computation)
ComputationGraph graph_
Definition: nnet-compile.h:64
void ComputeDerivNeeded(const std::vector< std::vector< int32 > > &steps, const std::vector< int32 > &step_to_segment, std::vector< bool > *deriv_needed)
void ComputeComputationPhases(const Nnet &nnet, const ComputationGraph &graph, std::vector< std::vector< std::vector< int32 > > > *phases_per_segment)
This function divides a computation into 'phases', where a 'phase' is a collection of cindexes which ...
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
void OutputDebugInfo(NnetComputation *computation) const
std::vector< std::pair< int32, int32 > > cindex_id_to_location_
This maps each cindex_id to its location.
Definition: nnet-compile.h:159
void AddCommands(const std::vector< bool > &deriv_needed, const std::vector< int32 > &step_to_segment, NnetComputation *computation)
void CreateStepInfo ( const std::vector< bool > &  deriv_needed,
const std::vector< int32 > &  step_to_segment,
std::vector< std::vector< int32 > > *  by_step,
NnetComputation computation 
)
private

Definition at line 279 of file nnet-compile.cc.

References Compiler::cindex_id_to_location_, ComputationGraph::cindexes, Compiler::ComputeInputLocationsList(), ComputationGraph::dependencies, Compiler::StepInfo::deriv, Compiler::StepInfo::deriv_parts, NetworkNode::descriptor, NetworkNode::dim, NetworkNode::Dim(), SumDescriptor::Dim(), Descriptor::Dim(), NetworkNode::dim_offset, Nnet::GetNode(), Compiler::GetStrideType(), Compiler::graph_, if(), Compiler::StepInfo::input_locations_list, KALDI_ASSERT, KALDI_PARANOID_ASSERT, kaldi::nnet3::kDescriptor, kaldi::nnet3::kDimRange, NnetComputation::NewMatrix(), NnetComputation::NewSubMatrix(), Compiler::nnet_, Compiler::StepInfo::node_index, NetworkNode::node_type, Descriptor::NumParts(), Compiler::StepInfo::output_cindex_ids, Compiler::StepInfo::output_indexes, Descriptor::Part(), Compiler::StepInfo::segment, Compiler::steps_, Compiler::StepInfo::value, and Compiler::StepInfo::value_parts.

Referenced by Compiler::CreateComputation().

283  {
284  KALDI_ASSERT(!by_step->empty());
285  int32 num_steps = by_step->size();
286  steps_.resize(num_steps);
287  for (int32 step = 0; step < num_steps; step++) {
288  StepInfo &this_info = steps_[step];
289  this_info.output_cindex_ids.swap((*by_step)[step]);
290  this_info.segment = step_to_segment[step];
291  int32 num_ids = this_info.output_cindex_ids.size();
292  this_info.output_indexes.resize(num_ids);
293  for (int32 row_index = 0; row_index < num_ids; row_index++)
294  this_info.output_indexes[row_index] =
295  graph_.cindexes[this_info.output_cindex_ids[row_index]].second;
296  if (num_ids > 0) {
297  // node id's of all Cindexes are the same, so just use first one.
298  this_info.node_index =
299  graph_.cindexes[this_info.output_cindex_ids.front()].first;
300  } else {
301  // it's possible to have an empty step if it's the component-input step of
302  // a GeneralComponent that does not always have dependencies, such as the
303  // ConstantFunctionComponent. This is just a kind of placeholder; it will
304  // generate no commands. The next command works because the next
305  // step will be the propagate for that Component, whose node-index is one
306  // more than the component-input node.
307  KALDI_ASSERT((step+1) < by_step->size() && !(*by_step)[step+1].empty());
308  this_info.node_index =
309  graph_.cindexes[(*by_step)[step+1][0]].first - 1;
310  KALDI_ASSERT(this_info.node_index >= 0);
311  continue; // we don't need to do anything else for this step.
312  }
313  const NetworkNode &node = nnet_.GetNode(this_info.node_index);
314  int32 num_rows = num_ids, num_cols = node.Dim(nnet_);
315 
316  if (node.node_type != kDimRange) {
317  MatrixStrideType stride_type = GetStrideType(this_info.node_index);
318  this_info.value = computation->NewMatrix(num_rows, num_cols,
319  stride_type);
320  if (deriv_needed[step])
321  this_info.deriv = computation->NewMatrix(num_rows, num_cols,
322  stride_type);
323  } else {
324  // kDimRange. Will just be a sub-matrix of a Component or Input node.
325  int32 cindex_id = this_info.output_cindex_ids.front(),
326  input_cindex_id = graph_.dependencies[cindex_id][0],
327  input_step = cindex_id_to_location_[input_cindex_id].first;
328  KALDI_ASSERT(input_step != -1 && input_step < step);
329  KALDI_PARANOID_ASSERT(this_info.output_indexes ==
330  steps_[input_step].output_indexes);
331  this_info.value = computation->NewSubMatrix(steps_[input_step].value,
332  0, -1,
333  node.dim_offset, node.dim);
334  if (deriv_needed[step])
335  this_info.deriv = computation->NewSubMatrix(steps_[input_step].deriv,
336  0, -1,
337  node.dim_offset, node.dim);
338  }
339  if (node.node_type == kDescriptor) {
340  // we have a couple of things to do: set up input_locations_list which
341  // says where we copy the data from, and also set up value_parts and
342  // possibly deriv_parts.
343  const Descriptor &desc = node.descriptor;
344  int32 num_parts = desc.NumParts();
345  KALDI_ASSERT(num_parts > 0);
346  // set up input_locations_list.
347  this_info.input_locations_list.resize(num_parts);
348  for (int32 part = 0; part < num_parts; part++)
349  ComputeInputLocationsList(step, part,
350  &(this_info.input_locations_list[part]));
351  // set up value_parts and deriv_parts.
352  if (num_parts == 1) {
353  this_info.value_parts.push_back(this_info.value);
354  if (deriv_needed[step])
355  this_info.deriv_parts.push_back(this_info.deriv);
356  } else { // num_parts > 1.
357  int32 cur_dim_offset = 0;
358  // Have multiple parts, so need to set up sub-matrices.
359  this_info.value_parts.resize(num_parts);
360  if (deriv_needed[step])
361  this_info.deriv_parts.resize(num_parts);
362  for (int32 p = 0; p < num_parts; p++) {
363  const SumDescriptor &this_part = desc.Part(p);
364  int32 this_dim = this_part.Dim(nnet_);
365  this_info.value_parts[p] =
366  computation->NewSubMatrix(this_info.value,
367  0, -1,
368  cur_dim_offset, this_dim);
369  if (deriv_needed[step])
370  this_info.deriv_parts[p] =
371  computation->NewSubMatrix(this_info.deriv,
372  0, -1,
373  cur_dim_offset, this_dim);
374  cur_dim_offset += this_dim;
375  }
376  KALDI_ASSERT(cur_dim_offset == desc.Dim(nnet_));
377  }
378  }
379  }
380 }
MatrixStrideType GetStrideType(int32 node_index) const
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
ComputationGraph graph_
Definition: nnet-compile.h:64
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...
MatrixStrideType
Definition: matrix-common.h:44
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:182
int32 Dim(const Nnet &nnet) const
Definition: nnet-nnet.cc:33
if(num_rows_==0) return
void ComputeInputLocationsList(int32 step, int32 part_index, std::vector< std::vector< std::pair< int32, int32 > > > *input_locations) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
std::vector< std::pair< int32, int32 > > cindex_id_to_location_
This maps each cindex_id to its location.
Definition: nnet-compile.h:159
void DeallocateMatrices ( const std::vector< int32 > &  whole_submatrices,
const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

Definition at line 1278 of file nnet-compile.cc.

References NnetComputation::commands, Compiler::StepInfo::deriv, Nnet::GetNodeNames(), rnnlm::i, ComputationRequest::inputs, Nnet::IsInputNode(), Nnet::IsOutputNode(), KALDI_ASSERT, kaldi::nnet3::kDeallocMatrix, NnetComputation::matrices, Compiler::nnet_, Compiler::StepInfo::node_index, Compiler::requests_, Compiler::steps_, NnetComputation::submatrices, and Compiler::StepInfo::value.

Referenced by Compiler::AddCommands().

1280  {
1281  // This adds the commands to destroy all the matrices- but not the
1282  // ones that might be needed as outputs of the computation. The ones that
1283  // are spared from destruction are those corresponding to outputs of the
1284  // computation, and those corresponding to input derivatives that were
1285  // requested by the user.
1286  int32 num_matrices = computation->matrices.size();
1287  std::vector<bool> will_destroy(num_matrices, true);
1288 
1289  int32 num_steps = steps_.size();
1290  for (int32 step = 0; step < num_steps; step++) {
1291  const StepInfo &step_info = steps_[step];
1292  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1293  if (nnet_.IsOutputNode(step_info.node_index)) {
1294  // steps corresponding to output nodes need to have their "value" kept.
1295  int32 value_matrix_index =
1296  computation->submatrices[step_info.value].matrix_index;
1297  will_destroy[value_matrix_index] = false;
1298  } else if (nnet_.IsInputNode(step_info.node_index)) {
1299  // steps corresponding to input nodes need to have their "deriv" kept, but
1300  // only if the corresponding input derivative was requested. (we don't
1301  // need to worry about whether outputs were requested, because if they
1302  // were not requested we would not be computing them in the first place).
1303  std::string input_name = nnet_.GetNodeNames()[step_info.node_index];
1304  int32 i = 0, num_inputs = request.inputs.size();
1305  bool has_deriv = false;
1306  for (; i < num_inputs; i++) {
1307  if (input_name == request.inputs[i].name) {
1308  has_deriv = request.inputs[i].has_deriv;
1309  break;
1310  }
1311  }
1312  KALDI_ASSERT(i != num_inputs); // assert we found an input-request with
1313  // this name
1314  if (has_deriv) {
1315  int32 deriv_matrix_index =
1316  computation->submatrices[step_info.deriv].matrix_index;
1317  will_destroy[deriv_matrix_index] = false;
1318  }
1319  }
1320  }
1321  // note: matrix-index 0 is the empty matrix.
1322  for (int32 m = 1; m < num_matrices; m++) {
1323  if (will_destroy[m]) {
1324  int32 submatrix_index = whole_submatrices[m];
1325  computation->commands.push_back(
1326  NnetComputation::Command(kDeallocMatrix, submatrix_index));
1327  }
1328  }
1329 }
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
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
Definition: nnet-nnet.cc:120
const std::vector< std::string > & GetNodeNames() const
returns vector of node names (needed by some parsing code, for instance).
Definition: nnet-nnet.cc:63
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void DefineMatrices ( NnetComputation computation) const
private
void DefineSubmatrices ( NnetComputation computation)
private
MatrixStrideType GetStrideType ( int32  node_index) const
private

Definition at line 252 of file nnet-compile.cc.

References NetworkNode::component_index, Nnet::GetComponent(), Nnet::GetNode(), Nnet::IsComponentInputNode(), Nnet::IsComponentNode(), kaldi::kDefaultStride, kaldi::nnet3::kInputContiguous, kaldi::nnet3::kOutputContiguous, kaldi::kStrideEqualNumCols, Compiler::nnet_, Component::Properties(), and NetworkNode::u.

Referenced by Compiler::CreateStepInfo().

252  {
253  int32 component_node_index;
254  bool is_input;
255  if (nnet_.IsComponentInputNode(node_index)) {
256  // this node is for the input to a component.
257  component_node_index = node_index + 1;
258  is_input = true;
259  } else if (nnet_.IsComponentNode(node_index)) {
260  component_node_index = node_index;
261  is_input = false;
262  } else {
263  return kDefaultStride;
264  }
265  const NetworkNode &node = nnet_.GetNode(component_node_index);
266  const Component *c = nnet_.GetComponent(node.u.component_index);
267  if (is_input) {
268  return (c->Properties() & kInputContiguous) ?
270  } else {
271  return (c->Properties() & kOutputContiguous) ?
273  }
274 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
bool IsComponentNode(int32 node) const
Returns true if this is a component node, meaning that it is of type kComponent.
Definition: nnet-nnet.cc:132
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
bool IsComponentInputNode(int32 node) const
Returns true if this is component-input node, i.e.
Definition: nnet-nnet.cc:172
bool IsInputStep ( int32  step) const
private

Definition at line 382 of file nnet-compile.cc.

References Nnet::GetNode(), KALDI_ASSERT, kaldi::nnet3::kInput, Compiler::nnet_, Compiler::StepInfo::node_index, NetworkNode::node_type, and Compiler::steps_.

Referenced by Compiler::CompileBackward(), and Compiler::CompileForward().

382  {
383  KALDI_ASSERT(step >= 0);
384  if (step >= steps_.size())
385  return false;
386  const StepInfo &step_info = steps_[step];
387  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
388  return (node.node_type == kInput);
389 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void OutputDebugInfo ( NnetComputation computation) const
private

Definition at line 1331 of file nnet-compile.cc.

References kaldi::nnet3::AppendCindexes(), NnetComputation::MatrixDebugInfo::cindexes, Compiler::StepInfo::deriv, NnetComputation::MatrixDebugInfo::is_deriv, NnetComputation::IsWholeMatrix(), NnetComputation::matrices, NnetComputation::matrix_debug_info, Compiler::StepInfo::node_index, Compiler::StepInfo::output_indexes, Compiler::steps_, NnetComputation::submatrices, and Compiler::StepInfo::value.

Referenced by Compiler::CreateComputation().

1331  {
1332  int32 num_matrices = computation->matrices.size(),
1333  num_steps = steps_.size();
1334  computation->matrix_debug_info.resize(num_matrices);
1335  for (int32 step = 0; step < num_steps; step++) {
1336  const StepInfo &step_info = steps_[step];
1337  if (step_info.value == 0)
1338  continue; // e.g. input step for ConstantComponent.
1339  if (!computation->IsWholeMatrix(step_info.value))
1340  continue;
1341  int32 value_matrix = computation->submatrices[step_info.value].matrix_index;
1342  int32 deriv_matrix = 0;
1343  if (step_info.deriv != 0 && computation->IsWholeMatrix(step_info.deriv))
1344  deriv_matrix = computation->submatrices[step_info.deriv].matrix_index;
1345 
1346  NnetComputation::MatrixDebugInfo &debug_info =
1347  computation->matrix_debug_info[value_matrix];
1348  debug_info.is_deriv = false;
1349  AppendCindexes(step_info.node_index, step_info.output_indexes,
1350  &debug_info.cindexes);
1351  if (deriv_matrix != 0) {
1352  NnetComputation::MatrixDebugInfo &deriv_debug_info =
1353  computation->matrix_debug_info[deriv_matrix];
1354  deriv_debug_info.is_deriv = true;
1355  deriv_debug_info.cindexes = debug_info.cindexes;
1356  }
1357  }
1358 }
void AppendCindexes(int32 node, const std::vector< Index > &indexes, std::vector< Cindex > *out)
Appends to 'out' the pairs (node, indexes[0]), (node, indexes[1]), ...
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void SetUpPrecomputedIndexes ( const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

Definition at line 1224 of file nnet-compile.cc.

References NetworkNode::component_index, NnetComputation::component_precomputed_indexes, NnetComputation::PrecomputedIndexesInfo::data, Nnet::GetComponent(), Nnet::GetNode(), NnetComputation::PrecomputedIndexesInfo::input_indexes, KALDI_ASSERT, kaldi::nnet3::kComponent, ComputationRequest::misc_info, ComputationRequest::NeedDerivatives(), Compiler::nnet_, Compiler::StepInfo::node_index, NetworkNode::node_type, Compiler::StepInfo::output_indexes, NnetComputation::PrecomputedIndexesInfo::output_indexes, Compiler::StepInfo::precomputed_indexes_index, Component::PrecomputeIndexes(), Compiler::requests_, Compiler::steps_, and NetworkNode::u.

Referenced by Compiler::AddCommands().

1226  {
1227  int32 num_steps = steps_.size();
1228  KALDI_ASSERT(computation->component_precomputed_indexes.empty());
1229  // the zeroth commponent is special, contains a NULL pointer.
1230  computation->component_precomputed_indexes.resize(1);
1231  for (int32 step = 0; step < num_steps; step++) {
1232  StepInfo &step_info = steps_[step];
1233  int32 node_index = step_info.node_index;
1234  const NetworkNode &node = nnet_.GetNode(node_index);
1235  // There is only something to do for nodes of type Component.
1236  if (node.node_type != kComponent)
1237  continue;
1238  const StepInfo &input_step_info = steps_[step - 1];
1239  int32 component_index = node.u.component_index;
1240  int32 input_node_index = input_step_info.node_index;
1241  KALDI_ASSERT(input_node_index == node_index - 1);
1242  const std::vector<Index> &input_indexes = input_step_info.output_indexes;
1243  const std::vector<Index> &output_indexes = step_info.output_indexes;
1244 
1245  const Component *component = nnet_.GetComponent(component_index);
1246 
1247  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1248  bool need_derivs = request.NeedDerivatives();
1249  ComponentPrecomputedIndexes *precomputed_indexes =
1250  component->PrecomputeIndexes(request.misc_info,
1251  input_indexes, output_indexes,
1252  need_derivs);
1253  if (precomputed_indexes == NULL) {
1254  // e.g. simple Components, and some other Components, will return NULL for
1255  // precomputed_indexes.
1256  step_info.precomputed_indexes_index = 0;
1257  } else {
1258  step_info.precomputed_indexes_index =
1259  computation->component_precomputed_indexes.size();
1260 
1261  NnetComputation::PrecomputedIndexesInfo info;
1262  info.data = precomputed_indexes;
1263 
1264  if (!input_indexes.empty() && input_indexes.back().n == 1 &&
1265  !output_indexes.empty() && output_indexes.back().n == 1) {
1266  // If these conditions are true, it's *possible* that we are doing
1267  // 'shortcut' compilation. So just in case that's what's going on, we
1268  // store 'input_indexes' and 'output_indexes, which are needed by
1269  // the ExpandComputation() function that is used in that process.
1270  info.input_indexes = input_indexes;
1271  info.output_indexes = output_indexes;
1272  }
1273  computation->component_precomputed_indexes.push_back(info);
1274  }
1275  }
1276 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
virtual ComponentPrecomputedIndexes * PrecomputeIndexes(const MiscComputationInfo &misc_info, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, bool need_backprop) const
This function must return NULL for simple Components.
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
BaseFloat SplitByScale ( const SumDescriptor descriptor,
const std::vector< std::vector< std::pair< int32, int32 > > > &  input_locations_list,
std::vector< std::pair< BaseFloat, std::vector< std::vector< std::pair< int32, int32 > > > > > *  split_locations_lists 
) const
private

This function helps to handle scalar factors in Descriptors (expressions like `Scale(-1.0, <descriptor)`).

It splits an input_locations_list for one SumDescriptor (consisting of one of the appended-together parts of a Descriptor) by scale, such that each split-up locations_list corresponds to a single scaling factor. The scaling factors are all 1.0 by default, but may be different from 1.0 if the user uses `Scale(...)` expressions in descriptors, e.g. `Scale(-1.0, lstm1.z)`. To help efficiency, this function treats the case where all the scales in the expression are the same (usually 1.0), as a special case. In this case, 'split_locations_lists' will be empty and the shared scale (e.g. 1.0) is returned.

Parameters
[in]descriptorThe SumDescriptor for which we're getting scalar factors.
[in]input_locations_listThis is one element of the input_locations_list from the StepInfo of the step we are computing, corresponding to this SumDescriptor (i.e. one part of the Descriptor). It is indexed by row-index, then it is a list of pairs (step, row-index), representing source Cindexes of a summation. This function will work out what scaling factors the pairs in these lists have.
[out]split_locations_listsWe write to this location. If all the scaling factors are the same this will be set to the empty list and the common scaling factor returned. Otherwise +infinity will be returned and the split-up list will be written to the location. Each element (*split_locations_lists)[i] will be set to a pair (alpha, partial_input_locations_list) where alpha is the scaling factor associated with this split-up piece (e.g. -1.0 if it was part of an expression like `Scale(-1.0, lstm1.z)`), and 'partial_input_locations_list' is a vector with the same dimension as 'input_locations_list' (indexed by row-index), where partial_input_locations_list[r] will contain a subset of the pairs present in input_locations_list[r], and if we were to append together all the (*split_locations_lists)[*].second.partial_input_locations_list[r], we'd get a list with the same members as input_locations_list[r], although not necessarily in the same order.
Returns
In the general case (where multiple scales are used), returns +infinity and sets 'split_locations_lists' to the split-up list. In the special, but more common case where only a single scale is used, return that scale (1.0 will be the most common value) and set 'split_locations_lists' to empty; in this special case, which has been made a special case for efficiency reasons, the user should directly use the un-split locations list in 'input_locations_list'.

Definition at line 542 of file nnet-compile.cc.

References SumDescriptor::GetNodeDependencies(), SumDescriptor::GetScaleForNode(), rnnlm::i, rnnlm::j, KALDI_ASSERT, kaldi::SortAndUniq(), and Compiler::steps_.

Referenced by Compiler::CompileBackwardSumDescriptor(), and Compiler::CompileForwardSumDescriptor().

547  {
548  split_locations_lists->clear();
549  // alpha_to_nodes maps from the scale alpha to the list of nodes which are
550  // given that scale.
551  std::map<BaseFloat, std::vector<int32> > alpha_to_nodes;
552  { // This block compute `alpha_to_nodes`.
553  std::vector<int32> nodes;
554  descriptor.GetNodeDependencies(&nodes);
555  SortAndUniq(&nodes);
556  // Now `nodes` is a list of the graph node indexes that are referred to
557  // in the descriptor. E.g. if the Descriptor represents
558  // 'Sum(tdnn1, Offset(tdnn2, -2))' then `nodes` would contain the
559  // integer node indexes for graph-nodes 'tdnn1' and 'tdnn2'.
560  for (size_t i = 0; i < nodes.size(); i++) {
561  int32 node = nodes[i];
562  BaseFloat alpha = descriptor.GetScaleForNode(node);
563  KALDI_ASSERT(alpha - alpha == 0.0); // check it's not infinity.
564  alpha_to_nodes[alpha].push_back(node);
565  }
566  }
567 
568  if (alpha_to_nodes.size() == 1) {
569  // If all the alpha values are the same we treat it as a special case
570  // for efficiency, to avoid a redundant copy of the contents of
571  // 'input_locations_list'.
572  return alpha_to_nodes.begin()->first;
573  }
574 
575  // `steps_used` will be a list of all step indexes that appear as `.first`
576  // elements in `input_locations_list`.
577  unordered_set<int32> steps_used;
578  { // This block computes `steps_used`.
579  int32 cur_step = -1000;
580  std::vector<std::vector<std::pair<int32,int32> > >::const_iterator
581  iter = input_locations_list.begin(),
582  end = input_locations_list.end();
583  for (; iter != end; ++iter) {
584  std::vector<std::pair<int32,int32> >::const_iterator
585  pair_iter = iter->begin(),
586  pair_end = iter->end();
587  for (; pair_iter != pair_end; ++pair_iter) {
588  if (pair_iter->first != cur_step) {
589  cur_step = pair_iter->first;
590  steps_used.insert(cur_step);
591  }
592  }
593  }
594  }
595 
596  // `node_to_steps` will be a map from graph node index to the list of steps
597  // which are present in `steps_used` and which are associated with that graph
598  // node.
599  std::map<int32, std::vector<int32> > node_to_steps;
600  { // This block computes `node_to_steps`.
601  unordered_set<int32>::const_iterator
602  step_iter = steps_used.begin(), step_end = steps_used.end();
603  for (; step_iter != step_end; ++step_iter) {
604  int32 step_index = *step_iter;
605  KALDI_ASSERT(static_cast<size_t>(step_index) < steps_.size());
606  int32 node_index = steps_[step_index].node_index;
607  node_to_steps[node_index].push_back(step_index);
608  }
609  }
610 
611  int32 num_rows = input_locations_list.size();
612  split_locations_lists->resize(alpha_to_nodes.size());
613  // `step_to_index` will map from the step-index to the index into
614  // `split_locations_lists`; each index is associated with a different value of
615  // the scale `alpha`.
616  std::vector<int32> step_to_locations_index(steps_.size(), -1);
617  { // This block computes `step_to_index` and also sets the `alpha` values
618  // which are present as (*split_locations_lists)[*].first.
619  std::map<BaseFloat, std::vector<int32> >::const_iterator
620  iter = alpha_to_nodes.begin(), end = alpha_to_nodes.end();
621  int32 split_locations_index = 0;
622  for (; iter != end; ++iter, ++split_locations_index) {
623  BaseFloat alpha = iter->first;
624  const std::vector<int32> &nodes = iter->second;
625  (*split_locations_lists)[split_locations_index].first = alpha;
626  (*split_locations_lists)[split_locations_index].second.resize(num_rows);
627  for (size_t i = 0; i < nodes.size(); i++) {
628  int32 node_index = nodes[i];
629  KALDI_ASSERT(node_to_steps.count(node_index) != 0);
630  const std::vector<int32> &steps = node_to_steps[node_index];
631  for (size_t j = 0; j < steps.size(); j++) {
632  int32 step_index = steps[j];
633  KALDI_ASSERT(step_index >= 0 &&
634  step_to_locations_index[step_index] == -1);
635  step_to_locations_index[step_index] = split_locations_index;
636  }
637  }
638  }
639  }
640 
641  { // This block populates 'split_locations_lists[*].second' with the
642  // split-by-alpha version of 'input_locations_list'
643  for (int32 r = 0; r < num_rows; r++) {
644  const std::vector<std::pair<int32,int32> > &this_list =
645  input_locations_list[r];
646  std::vector<std::pair<int32,int32> >::const_iterator
647  pair_iter = this_list.begin(),
648  pair_end = this_list.end();
649  for (; pair_iter != pair_end; ++pair_iter) {
650  int32 step = pair_iter->first,
651  split_locations_index = step_to_locations_index[step];
652  (*split_locations_lists)[split_locations_index].second[r].push_back(
653  *pair_iter);
654  }
655  }
656  }
657  return std::numeric_limits<BaseFloat>::infinity();
658 }
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
Definition: stl-utils.h:39
float BaseFloat
Definition: kaldi-types.h:29
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169

Member Data Documentation

std::vector<std::pair<int32, int32> > cindex_id_to_location_
private

This maps each cindex_id to its location.

However, you should not rely on its accuracy for cindex_ids that correspond to the Descriptors at Component inputs, since it's possible in principle for such cindex_ids to exist at >1 location. (This is not a problem in practice, because we only need this for the outputs of component-nodes, and for computation inputs). A location is a pair (step-index, matrix-row-index).

Definition at line 159 of file nnet-compile.h.

Referenced by Compiler::ComputeInputLocationsList(), Compiler::ComputeStepDependencies(), Compiler::CreateComputation(), and Compiler::CreateStepInfo().


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