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 1149 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().

1150  {
1151  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1152  const StepInfo &step_info = steps_[step];
1153  int32 input_step = step - 1;
1154  const StepInfo &input_step_info = steps_[input_step];
1155  int32 node_index = step_info.node_index;
1156  const NetworkNode &node = nnet_.GetNode(node_index);
1157  KALDI_ASSERT(node.node_type == kComponent);
1158  int32 component_index = node.u.component_index;
1159  const Component *component = nnet_.GetComponent(component_index);
1160  int32 properties = component->Properties();
1161 
1162  int32 input_submatrix_index = input_step_info.value,
1163  output_submatrix_index = step_info.value,
1164  input_deriv_submatrix_index = input_step_info.deriv,
1165  output_deriv_submatrix_index = step_info.deriv,
1166  memo_index = (properties & kUsesMemo ? step : 0);
1167  KALDI_ASSERT(output_deriv_submatrix_index > 0 &&
1168  (input_deriv_submatrix_index > 0 ||
1169  properties & kUpdatableComponent));
1170 
1171  if (! (properties & kBackpropNeedsInput))
1172  input_submatrix_index = 0;
1173  if (! (properties & kBackpropNeedsOutput))
1174  output_submatrix_index = 0;
1175 
1176  NnetComputation::Command c(kBackprop,
1177  component_index,
1178  step_info.precomputed_indexes_index,
1179  input_submatrix_index,
1180  output_submatrix_index,
1181  output_deriv_submatrix_index,
1182  input_deriv_submatrix_index,
1183  memo_index);
1184  computation->commands.push_back(c);
1185 }
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:153
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddBackwardStepInput ( int32  step,
NnetComputation computation 
) const
private

Definition at line 1131 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().

1132  {
1133  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1134  const StepInfo &step_info = steps_[step];
1135  int32 node_index = step_info.node_index,
1136  deriv_submatrix_index = step_info.deriv;
1137  if (deriv_submatrix_index == 0)
1138  return; // Nothing to do.
1139  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
1140  const NetworkNode &node = nnet_.GetNode(node_index);
1141  // actually, currently the node type would always be kInput.
1142  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
1143 
1144  NnetComputation::Command c(kProvideOutput, deriv_submatrix_index, node_index);
1145  computation->commands.push_back(c);
1146 }
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:153
#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:153
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 1097 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().

1098  {
1099  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1100  const StepInfo &step_info = steps_[step];
1101  int32 input_step = step - 1;
1102  const StepInfo &input_step_info = steps_[input_step];
1103  int32 node_index = step_info.node_index;
1104  const NetworkNode &node = nnet_.GetNode(node_index);
1105  KALDI_ASSERT(node.node_type == kComponent);
1106  int32 component_index = node.u.component_index;
1107  const Component *component = nnet_.GetComponent(component_index);
1108 
1109  // note RE memo_index: we'll renumber them in optimization to get rid of gaps.
1110  // The use of 'step' as the memo index is OK because step > 0 if we're doing
1111  // forward propagation, there must be preceding steps for inputs or for
1112  // component-input nodes).
1113  int32 properties = component->Properties(),
1114  input_submatrix_index = input_step_info.value,
1115  output_submatrix_index = step_info.value,
1116  memo_index = (step_info.deriv > 0 && (properties & kUsesMemo) ? step : 0),
1117  store_stats = (requests_[0]->store_component_stats &&
1118  (properties & kStoresStats) ? 1 : 0);
1119 
1120  NnetComputation::Command c(kPropagate,
1121  component_index,
1122  step_info.precomputed_indexes_index,
1123  input_submatrix_index,
1124  output_submatrix_index,
1125  memo_index,
1126  store_stats);
1127  computation->commands.push_back(c);
1128 }
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:153
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 1080 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().

1081  {
1082  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
1083  const StepInfo &step_info = steps_[step];
1084  int32 node_index = step_info.node_index,
1085  submatrix_index = step_info.value;
1086  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
1087 
1088  const NetworkNode &node = nnet_.GetNode(node_index);
1089  // actually currently the node type would always be kInput.
1090  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
1091 
1092  NnetComputation::Command c(kAcceptInput, submatrix_index, node_index);
1093  computation->commands.push_back(c);
1094 }
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:153
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AllocateMatrices ( const std::vector< int32 > &  whole_submatrices,
NnetComputation computation 
) const
private

Definition at line 1189 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().

1190  {
1191  KALDI_ASSERT(computation->commands.empty());
1192  // Work out which matrices are inputs to the computation (or output-derivs,
1193  // which are also supplied as inputs to the computation); we won't be setting
1194  // these up.
1195  unordered_set<int32> input_and_oderiv_matrices;
1196  int32 num_steps = steps_.size();
1197  for (int32 step = 0; step < num_steps; step++) {
1198  const StepInfo &this_info = steps_[step];
1199  if (this_info.output_cindex_ids.empty())
1200  continue;
1201  int32 first_cindex_id = this_info.output_cindex_ids.front(),
1202  node_index = this_info.node_index;
1203  bool is_input = graph_.is_input[first_cindex_id],
1204  is_output = nnet_.IsOutputNode(node_index);
1205  if (is_input) {
1206  int32 value_submatrix_index = this_info.value,
1207  value_matrix_index =
1208  computation->submatrices[value_submatrix_index].matrix_index;
1209  input_and_oderiv_matrices.insert(value_matrix_index);
1210  }
1211  if (is_output && this_info.deriv != 0) {
1212  int32 deriv_submatrix_index = this_info.deriv,
1213  deriv_matrix_index =
1214  computation->submatrices[deriv_submatrix_index].matrix_index;
1215  input_and_oderiv_matrices.insert(deriv_matrix_index);
1216  }
1217  }
1218 
1219  int32 num_matrices = computation->matrices.size();
1220  for (int32 m = 1; m < num_matrices; m++) {
1221  // We don't set up the matrices that are inputs to the computation;
1222  // this happens when the user provides the input.
1223  if (input_and_oderiv_matrices.count(m) == 0) {
1224  // get a submatrix index that refers to the entire matrix.
1225  int32 submatrix_index = whole_submatrices[m];
1226 
1227  computation->commands.push_back(
1228  NnetComputation::Command(kAllocMatrix, submatrix_index));
1229  // Later in the optimization phase, it turns out that zeroing is not
1230  // necessary for some matrices, we'll remove the redundant kSetConst
1231  // commands.
1232  computation->commands.push_back(
1233  NnetComputation::Command(0.0, kSetConst, submatrix_index));
1234  }
1235  }
1236 }
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:153
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void CompileBackward ( int32  step,
NnetComputation computation 
)
private

Definition at line 1050 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().

1051  {
1052  KALDI_ASSERT(step < static_cast<int32>(steps_.size()));
1053  const StepInfo &step_info = steps_[step];
1054  int32 node_index = step_info.node_index;
1055  const NetworkNode &node = nnet_.GetNode(node_index);
1056 
1057  switch (node.node_type) {
1058  case kInput:
1059  AddBackwardStepInput(step, computation);
1060  if (!IsInputStep(step + 1)) // Make sure backward computation is nonempty.
1061  computation->commands.push_back(
1062  NnetComputation::Command(kNoOperationPermanent));
1063  break;
1064  case kDimRange:
1065  break; // Nothing to do.
1066  case kComponent:
1067  AddBackwardStepComponent(step, computation);
1068  break;
1069  case kDescriptor:
1070  CompileBackwardDescriptor(step, computation);
1071  break;
1072  default:
1073  KALDI_ERR << "Invalid node type";
1074  }
1075 }
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:153
#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 1029 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().

1030  {
1031  StepInfo &step_info = steps_[step];
1032  if (nnet_.IsOutputNode(step_info.node_index) &&
1033  step_info.deriv > 0) {
1034  int32 deriv_submatrix_index = step_info.deriv;
1035  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
1036  NnetComputation::Command c(kAcceptInput, deriv_submatrix_index,
1037  step_info.node_index);
1038  computation->commands.push_back(c);
1039  }
1040 
1041  // the top-level descriptor has a bunch of parts that we concatenate features
1042  // over.
1043  int32 num_parts = step_info.value_parts.size();
1044  for (int32 part = 0; part < num_parts; part++)
1045  CompileBackwardSumDescriptor(step, part,
1046  computation);
1047 }
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:153
#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 939 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().

944  {
945 
946  int32 num_rows = computation->submatrices[deriv_submatrix_index].num_rows,
947  input_num_rows =
948  computation->submatrices[input_deriv_submatrix_index].num_rows;
949  KALDI_ASSERT(indexes.size() == num_rows);
950  if (input_num_rows == num_rows) {
951  int32 i;
952  for (i = 0; i < num_rows; i++)
953  if (indexes[i] != i)
954  break;
955  if (i == num_rows) { // Simplest case: just matrix addition.
956  computation->commands.push_back(
957  NnetComputation::Command(alpha,
958  kMatrixAdd,
959  input_deriv_submatrix_index,
960  deriv_submatrix_index));
961 
962  return;
963  }
964  }
965  if (input_num_rows >= num_rows) {
966  // If there are no repeated elements in the "indexes" array, we can reverse
967  // the mapping and make it an operation of type kAddRows. TODO: change this
968  // to use kAddToRows, kCopyToRows, when implemented (will be more
969  // efficient).
970  std::vector<int32> reverse_indexes(input_num_rows, -1);
971  int32 i;
972  for (i = 0; i < num_rows; i++) {
973  int32 index_i = indexes[i];
974  KALDI_ASSERT(index_i >= -1 && index_i < input_num_rows);
975  if (index_i >= 0) {
976  if (reverse_indexes[index_i] == -1)
977  reverse_indexes[index_i] = i;
978  else
979  break;
980  } // note: there may be -1's in 'indexes', meaning just use zero.
981  }
982  if (i == num_rows) {
983  // There were no repeated elements, and this strategy will work.
984  int32 indexes_index = computation->indexes.size();
985  computation->indexes.push_back(reverse_indexes);
986  computation->commands.push_back(
987  NnetComputation::Command(alpha,
988  kAddRows,
989  input_deriv_submatrix_index,
990  deriv_submatrix_index,
991  indexes_index));
992  return;
993  }
994  }
995  std::vector<std::pair<int32, int32> > ranges;
996  if (HasContiguousProperty(indexes, &ranges)) {
997  // the operation can be set up as AddRowRanges.
998  if (static_cast<int32>(ranges.size()) != input_num_rows) {
999  KALDI_ASSERT(static_cast<int32>(ranges.size()) < input_num_rows);
1000  // extend with (-1, -1) pairs.
1001  ranges.resize(input_num_rows, std::pair<int32,int32>(-1, -1));
1002  }
1003  int32 indexes_ranges_index = computation->indexes_ranges.size();
1004  computation->indexes_ranges.push_back(ranges);
1005  computation->commands.push_back(
1006  NnetComputation::Command(alpha,
1007  kAddRowRanges,
1008  input_deriv_submatrix_index,
1009  deriv_submatrix_index,
1010  indexes_ranges_index));
1011  // TODO: if any of these ranges are quite long (summing over many rows), the
1012  // resulting code could be inefficient because the AddRowRanges kernels
1013  // takes time linear in the length of the range. Using a temporary matrix
1014  // with an intermediate size would make this more efficient in that case, so
1015  // the one command would be two commands (plus commands to set up and
1016  // destroy the temporary matrix).
1017  return;
1018  }
1019 
1020  // If you ever reach here, it means someone has used a type of network that we
1021  // don't yet support in the backprop. Basically this case can be handled by
1022  // creating a temporary matrix to reorder the matrix at deriv_submatrix_index,
1023  // (using CopyRows), and doing AddRowRanges from that.
1024  // It wouldn't be too much work.
1025  KALDI_ERR << "This case not implemented yet.";
1026 }
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 887 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().

891  {
892  // This function creates a command to handle an individual piece of the
893  // Descriptor, for backprop. Note: because the backprop case is a little
894  // trickier to implement efficiently on the GPU, there may be cases
895  // which we will refuse to implement backprop for if we get here.
896 
897 
898 
899  int32 first_value;
900  std::vector<int32> second_values;
901  if (ConvertToIndexes(submat_locations, &first_value,
902  &second_values)) {
903  int32 input_deriv_submatrix_index = first_value;
904  CompileBackwardFromIndexes(deriv_submatrix_index,
905  input_deriv_submatrix_index,
906  alpha,
907  second_values,
908  computation);
909  return;
910  } else {
911  // There are multiple source matrices.
912  std::vector<std::pair<int32, int32> > submat_locations_sorted;
913  std::sort(submat_locations_sorted.begin(), submat_locations_sorted.end());
914  if (IsSortedAndUniq(submat_locations_sorted)) {
915  // There are no repeats in any of the submat locations. This means that
916  // we can just use kAddToRowsMulti (i.e. AddToRows with pointer
917  // destination). If there were repeats, the CUDA kernel would require
918  // special synchronization so we don't allow it.
919  int32 indexes_multi_index = computation->indexes_multi.size();
920  computation->indexes_multi.push_back(submat_locations);
921  computation->commands.push_back(
922  NnetComputation::Command(alpha,
924  deriv_submatrix_index,
925  indexes_multi_index));
926  return;
927  }
928  // If you reach this point, there is a case that wasn't handled. Our
929  // intended strategy to handle it, if it's ever needed, is to create a
930  // temporary matrix consisting of all the unique submat_locations in the
931  // input. We would first recurse to CompileBackwardFromIndexes, and
932  // let it write to this temporary matrix; and then do the kAddToRowsMulti
933  // command as above to go from the temporary matrix to the multiple
934  // matrices.
935  KALDI_ERR << "This case not handled.";
936  }
937 }
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 818 of file nnet-compile.cc.

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

Referenced by Compiler::CompileBackwardSumDescriptor().

822  {
823  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
824  SplitLocationsBackward(submat_lists, &split_lists);
825  int32 size = split_lists.size(); // size may be zero e.g. for unused outputs.
826  for (int32 i = 0; i < size; i++)
828  deriv_submatrix_index,
829  alpha,
830  split_lists[i],
831  computation);
832 }
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 835 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().

836  {
837  const StepInfo &step_info = steps_[step];
838  int32 deriv_submatrix_index = step_info.deriv_parts[part_index];
839  KALDI_ASSERT(deriv_submatrix_index > 0); // or should not have called this.
840  const SumDescriptor &descriptor =
841  nnet_.GetNode(step_info.node_index).descriptor.Part(part_index);
842  // Note: `offset_term` appeared in the forward computation here but does not
843  // come into the backward computation.
844 
845  // `input_locations_list` is a vector indexed by row-index, with each element
846  // being a list of pairs (step, row_index) representing terms in a weighted
847  // sum.
848  const std::vector<std::vector<std::pair<int32,int32> > >
849  &input_locations_list = step_info.input_locations_list[part_index];
850 
851  // `split_locations_lists` is a vector of pairs `(alpha, locations_list)`
852  // where alpha is the scale in which these items appear in the
853  // summation and `locations_list` is the same format as `input_locations_list`
854  std::vector<std::pair<BaseFloat,
855  std::vector<std::vector<std::pair<int32,int32> > > > > split_locations_lists;
856  BaseFloat shared_alpha = SplitByScale(descriptor, input_locations_list,
857  &split_locations_lists);
858  if (shared_alpha - shared_alpha == 0.0) {
859  // If the returned value 'shared_alpha' is finite, this indicates that there
860  // was no need to split up 'input_locations_list' because all the alpha
861  // values (scales) were the same. We treat this case specially for
862  // efficiency reasons; this branch will be the most common branch.
863  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
864  ComputeDerivSubmatLocationsList(input_locations_list,
865  &submat_locations_list);
866  CompileBackwardFromSubmatLocationsList(deriv_submatrix_index,
867  shared_alpha,
868  submat_locations_list,
869  computation);
870  } else {
871  for (size_t i = 0; i < split_locations_lists.size(); i++) {
872  BaseFloat this_alpha = split_locations_lists[i].first;
873  KALDI_ASSERT(this_alpha - this_alpha == 0.0);
874  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
875  ComputeDerivSubmatLocationsList(split_locations_lists[i].second,
876  &submat_locations_list);
877  CompileBackwardFromSubmatLocationsList(deriv_submatrix_index,
878  this_alpha,
879  submat_locations_list,
880  computation);
881  }
882  }
883 }
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:153
#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 406 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().

407  {
408  KALDI_ASSERT(step < static_cast<int32>(steps_.size()));
409  const StepInfo &step_info = steps_[step];
410  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
411  switch (node.node_type) {
412  case kInput: // Note: input nodes appear before other node types.
413  AddForwardStepInput(step, computation);
414  if (!IsInputStep(step + 1)) // Make sure forward computation is nonempty.
415  computation->commands.push_back(
416  NnetComputation::Command(kNoOperationPermanent));
417  break;
418  case kDimRange: break; // Nothing to do.
419  case kComponent:
420  AddForwardStepComponent(step, computation);
421  break;
422  case kDescriptor:
423  CompileForwardDescriptor(step, computation);
424  break;
425  default:
426  KALDI_ERR << "Invalid node type";
427  }
428 
429 }
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:153
#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 432 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().

433  {
434  int32 num_parts = steps_[step].value_parts.size();
435  for (int32 part = 0; part < num_parts; part++)
436  CompileForwardSumDescriptor(step, part, computation);
437  const StepInfo &step_info = steps_[step];
438  if (nnet_.IsOutputNode(step_info.node_index)) {
439  // If the node is an output then we need to add commands to provide the
440  // output to the user, and possibly to get derivatives w.r.t. the output
441  // from the user.
442  int32 node_index = step_info.node_index,
443  submatrix_index = step_info.value;
444  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
445  NnetComputation::Command c(kProvideOutput, submatrix_index, node_index);
446  computation->commands.push_back(c);
447  }
448 }
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:153
#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 738 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().

743  {
744 
745  int32 input_num_rows =
746  computation->submatrices[input_submatrix_index].num_rows,
747  num_rows = indexes.size();
748  if (input_num_rows == num_rows) {
749  int32 i;
750  for (i = 0; i < num_rows; i++)
751  if (indexes[i] != i)
752  break;
753  if (i == num_rows) { // Simplest case: just matrix addition.
754  computation->commands.push_back(
755  NnetComputation::Command(alpha, kMatrixAdd,
756  value_submatrix_index,
757  input_submatrix_index));
758 
759  return;
760  }
761  }
762  // if we got to here, it's not just a case of matrix-copy or matrix-add,
763  // but it's still from a single source matrix.
764  int32 indexes_index = computation->indexes.size();
765  computation->indexes.push_back(indexes);
766  computation->commands.push_back(
767  NnetComputation::Command(alpha, kAddRows, value_submatrix_index,
768  input_submatrix_index, indexes_index));
769  return;
770 }
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 772 of file nnet-compile.cc.

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

Referenced by Compiler::CompileForwardFromSubmatLocationsList().

776  {
777 
778  int32 input_submatrix_index = -1;
779  std::vector<int32> indexes;
780  if (ConvertToIndexes(submat_locations, &input_submatrix_index, &indexes)) {
781  CompileForwardFromIndexes(value_submatrix_index,
782  input_submatrix_index,
783  alpha,
784  indexes,
785  computation);
786  return;
787  } else {
788  // There are multiple source matrices.
789  int32 indexes_multi_index = computation->indexes_multi.size();
790  computation->indexes_multi.push_back(submat_locations);
791  computation->commands.push_back(
792  NnetComputation::Command(alpha, kAddRowsMulti,
793  value_submatrix_index,
794  indexes_multi_index));
795  return;
796  }
797 }
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 799 of file nnet-compile.cc.

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

Referenced by Compiler::CompileForwardSumDescriptor().

803  {
804  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
805  SplitLocations(submat_lists, &split_lists);
806  int32 size = split_lists.size();
807  // note: `size` may be empty in unusual cases so don't assert that it's
808  // nonzero.
809  for (int32 i = 0; i < size; i++)
811  value_submatrix_index,
812  alpha,
813  split_lists[i],
814  computation);
815 }
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 676 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().

677  {
678  const StepInfo &step_info = steps_[step];
679  int32 value_submatrix_index = step_info.value_parts[part_index];
680  const SumDescriptor &descriptor =
681  nnet_.GetNode(step_info.node_index).descriptor.Part(part_index);
682 
683  BaseFloat offset_term = descriptor.GetScaleForNode(-1);
684  if (offset_term != 0.0) {
685  computation->commands.push_back(
686  NnetComputation::Command(offset_term, kSetConst,
687  value_submatrix_index));
688  // if offset_term == 0.0 there's no need to do this, because
689  // we zeroed the matrix when we allocated it; search in this
690  // file for kSetConst to see the code. If we are redundantly
691  // setting the value, this will later be optimized out (in the
692  // common cases).
693  }
694 
695 
696  // `input_locations_list` is a vector indexed by row-index, with each element
697  // being a list of pairs (step, row_index) representing terms in a weighted
698  // sum.
699  const std::vector<std::vector<std::pair<int32,int32> > >
700  &input_locations_list = step_info.input_locations_list[part_index];
701 
702  // `split_locations_lists` is a vector of pairs `(alpha, locations_list)`
703  // where alpha is the scale in which these items appear in the
704  // summation and `locations_list` is the same format as `input_locations_list`
705  std::vector<std::pair<BaseFloat,
706  std::vector<std::vector<std::pair<int32,int32> > > > > split_locations_lists;
707  BaseFloat shared_alpha = SplitByScale(descriptor, input_locations_list,
708  &split_locations_lists);
709  if (shared_alpha - shared_alpha == 0.0) {
710  // If the returned value 'shared_alpha' is finite, this indicates that there was no
711  // need to split up 'input_locations_list' because all the alpha values
712  // (scales) were the same. We treat this case specially for efficiency
713  // reasons; this branch will be the most common branch.
714  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
715  ComputeValueSubmatLocationsList(input_locations_list,
716  &submat_locations_list);
718  value_submatrix_index,
719  shared_alpha,
720  submat_locations_list,
721  computation);
722  } else {
723  for (size_t i = 0; i < split_locations_lists.size(); i++) {
724  BaseFloat this_alpha = split_locations_lists[i].first;
725  KALDI_ASSERT(this_alpha - this_alpha == 0.0);
726  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
727  ComputeValueSubmatLocationsList(split_locations_lists[i].second,
728  &submat_locations_list);
730  value_submatrix_index,
731  this_alpha,
732  submat_locations_list,
733  computation);
734  }
735  }
736 }
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:153
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 531 of file nnet-compile.cc.

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

Referenced by Compiler::CompileBackwardSumDescriptor().

534  {
535  submat_locations_list->clear();
536  submat_locations_list->resize(input_locations_list.size());
537  int32 size = submat_locations_list->size();
538  for (int32 i = 0; i < size; i++) {
539  const std::vector<std::pair<int32, int32> > &this_list = input_locations_list[i];
540  std::vector<std::pair<int32, int32> > &this_submat_list = (*submat_locations_list)[i];
541  this_submat_list.reserve(this_list.size());
542  std::vector<std::pair<int32, int32> >::const_iterator
543  input_iter = this_list.begin(), input_end = this_list.end();
544  for (; input_iter != input_end; ++input_iter) {
545  int32 step = input_iter->first,
546  deriv_submat_index = steps_[step].deriv,
547  row = input_iter->second;
548  if (deriv_submat_index > 0)
549  this_submat_list.push_back(std::pair<int32,int32>(deriv_submat_index,
550  row));
551  }
552  }
553 }
std::vector< StepInfo > steps_
Definition: nnet-compile.h:153
void ComputeInputLocationsList ( int32  step,
int32  part_index,
std::vector< std::vector< std::pair< int32, int32 > > > *  input_locations 
) const
private

Definition at line 457 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().

460  {
461 
462  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
463  const StepInfo &step_info = steps_[step];
464  const std::vector<Index> &output_indexes = step_info.output_indexes;
465  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
466  const SumDescriptor &descriptor = node.descriptor.Part(part_index);
467  int32 num_indexes = output_indexes.size();
468  submat_locations_list->clear();
469  submat_locations_list->resize(num_indexes);
470 
471  for (int32 i = 0; i < num_indexes; i++) {
472  const Index &index = output_indexes[i];
473  std::vector<std::pair<int32, int32> > &this_locations_list =
474  (*submat_locations_list)[i];
475  if (index.t != kNoTime) {
476  // a real Index, not a 'blank' one
477  // ('blank' indexes are inserted by some non-simple Components to
478  // satisfy internal constraints.
479  std::vector<int32> input_cindex_ids;
480  std::vector<Cindex> input_cindexes;
481  CindexSet cindex_set(graph_);
482  bool ans = descriptor.IsComputable(index, cindex_set, &input_cindexes);
483  // earlier compilation stages should have checked that it is computable,
484  // and the graph should still contain required inputs.
485  KALDI_ASSERT(ans);
486  std::sort(input_cindexes.begin(), input_cindexes.end());
487  int32 size = input_cindexes.size();
488  input_cindex_ids.resize(size);
489  for (int32 j = 0; j < size; j++) {
490  int32 c = graph_.GetCindexId(input_cindexes[j]);
491  KALDI_ASSERT(c != -1);
492  input_cindex_ids[j] = c;
493  }
494  this_locations_list.resize(size);
495  for (int32 j = 0; j < size; j++)
496  this_locations_list[j] = cindex_id_to_location_[input_cindex_ids[j]];
497  } else {
498  this_locations_list.clear();
499  }
500  }
501 }
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:153
#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:161
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:161
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 503 of file nnet-compile.cc.

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

Referenced by Compiler::CompileForwardSumDescriptor().

506  {
507  submat_locations_list->clear();
508  submat_locations_list->resize(input_locations_list.size());
509  int32 size = submat_locations_list->size();
510  for (int32 i = 0; i < size; i++) {
511  const std::vector<std::pair<int32, int32> > &this_list =
512  input_locations_list[i];
513  std::vector<std::pair<int32, int32> > &this_submat_list =
514  (*submat_locations_list)[i];
515  this_submat_list.resize(this_list.size());
516  std::vector<std::pair<int32, int32> >::const_iterator
517  input_iter = this_list.begin(), input_end = this_list.end();
518  std::vector<std::pair<int32, int32> >::iterator iter =
519  this_submat_list.begin();
520  for (; input_iter != input_end; ++input_iter, ++iter) {
521  int32 step = input_iter->first,
522  value_submat_index = steps_[step].value,
523  row = input_iter->second;
524  iter->first = value_submat_index;
525  iter->second = row;
526  }
527  }
528 }
std::vector< StepInfo > steps_
Definition: nnet-compile.h:153
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:161
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_, NnetComputation::submatrices, 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  std::vector<int32>::const_iterator
326  iter = this_info.output_cindex_ids.begin(),
327  end = this_info.output_cindex_ids.end();
328  int32 source_cindex_id = -1;
329  for (; iter != end; ++iter) {
330  int32 cindex_id = *iter;
331  if (!graph_.dependencies[cindex_id].empty()) {
332  KALDI_ASSERT(graph_.dependencies[cindex_id].size() == 1);
333  source_cindex_id = graph_.dependencies[cindex_id][0];
334  break;
335  }
336  }
337  KALDI_ASSERT(source_cindex_id >= 0);
338  int32 input_step = cindex_id_to_location_[source_cindex_id].first;
339  KALDI_ASSERT(this_info.output_cindex_ids.size() ==
340  steps_[input_step].output_cindex_ids.size());
341  KALDI_ASSERT(input_step >= 0 && input_step < step);
342  KALDI_PARANOID_ASSERT(this_info.output_indexes ==
343  steps_[input_step].output_indexes);
344  this_info.value = computation->NewSubMatrix(steps_[input_step].value,
345  0, -1,
346  node.dim_offset, node.dim);
347  if (deriv_needed[step])
348  this_info.deriv = computation->NewSubMatrix(steps_[input_step].deriv,
349  0, -1,
350  node.dim_offset, node.dim);
351  }
352  if (node.node_type == kDescriptor) {
353  // we have a couple of things to do: set up input_locations_list which
354  // says where we copy the data from, and also set up value_parts and
355  // possibly deriv_parts.
356  const Descriptor &desc = node.descriptor;
357  int32 num_parts = desc.NumParts();
358  KALDI_ASSERT(num_parts > 0);
359  // set up input_locations_list.
360  this_info.input_locations_list.resize(num_parts);
361  for (int32 part = 0; part < num_parts; part++)
362  ComputeInputLocationsList(step, part,
363  &(this_info.input_locations_list[part]));
364  // set up value_parts and deriv_parts.
365  if (num_parts == 1) {
366  this_info.value_parts.push_back(this_info.value);
367  if (deriv_needed[step])
368  this_info.deriv_parts.push_back(this_info.deriv);
369  } else { // num_parts > 1.
370  int32 cur_dim_offset = 0;
371  // Have multiple parts, so need to set up sub-matrices.
372  this_info.value_parts.resize(num_parts);
373  if (deriv_needed[step])
374  this_info.deriv_parts.resize(num_parts);
375  for (int32 p = 0; p < num_parts; p++) {
376  const SumDescriptor &this_part = desc.Part(p);
377  int32 this_dim = this_part.Dim(nnet_);
378  this_info.value_parts[p] =
379  computation->NewSubMatrix(this_info.value,
380  0, -1,
381  cur_dim_offset, this_dim);
382  if (deriv_needed[step])
383  this_info.deriv_parts[p] =
384  computation->NewSubMatrix(this_info.deriv,
385  0, -1,
386  cur_dim_offset, this_dim);
387  cur_dim_offset += this_dim;
388  }
389  KALDI_ASSERT(cur_dim_offset == desc.Dim(nnet_));
390  }
391  }
392  KALDI_ASSERT(static_cast<int32>(this_info.output_cindex_ids.size()) ==
393  computation->submatrices[this_info.value].num_rows);
394  }
395 }
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:153
#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:161
void DeallocateMatrices ( const std::vector< int32 > &  whole_submatrices,
const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

Definition at line 1293 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().

1295  {
1296  // This adds the commands to destroy all the matrices- but not the
1297  // ones that might be needed as outputs of the computation. The ones that
1298  // are spared from destruction are those corresponding to outputs of the
1299  // computation, and those corresponding to input derivatives that were
1300  // requested by the user.
1301  int32 num_matrices = computation->matrices.size();
1302  std::vector<bool> will_destroy(num_matrices, true);
1303 
1304  int32 num_steps = steps_.size();
1305  for (int32 step = 0; step < num_steps; step++) {
1306  const StepInfo &step_info = steps_[step];
1307  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1308  if (nnet_.IsOutputNode(step_info.node_index)) {
1309  // steps corresponding to output nodes need to have their "value" kept.
1310  int32 value_matrix_index =
1311  computation->submatrices[step_info.value].matrix_index;
1312  will_destroy[value_matrix_index] = false;
1313  } else if (nnet_.IsInputNode(step_info.node_index)) {
1314  // steps corresponding to input nodes need to have their "deriv" kept, but
1315  // only if the corresponding input derivative was requested. (we don't
1316  // need to worry about whether outputs were requested, because if they
1317  // were not requested we would not be computing them in the first place).
1318  std::string input_name = nnet_.GetNodeNames()[step_info.node_index];
1319  int32 i = 0, num_inputs = request.inputs.size();
1320  bool has_deriv = false;
1321  for (; i < num_inputs; i++) {
1322  if (input_name == request.inputs[i].name) {
1323  has_deriv = request.inputs[i].has_deriv;
1324  break;
1325  }
1326  }
1327  KALDI_ASSERT(i != num_inputs); // assert we found an input-request with
1328  // this name
1329  if (has_deriv) {
1330  int32 deriv_matrix_index =
1331  computation->submatrices[step_info.deriv].matrix_index;
1332  will_destroy[deriv_matrix_index] = false;
1333  }
1334  }
1335  }
1336  // note: matrix-index 0 is the empty matrix.
1337  for (int32 m = 1; m < num_matrices; m++) {
1338  if (will_destroy[m]) {
1339  int32 submatrix_index = whole_submatrices[m];
1340  computation->commands.push_back(
1341  NnetComputation::Command(kDeallocMatrix, submatrix_index));
1342  }
1343  }
1344 }
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:153
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 397 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().

397  {
398  KALDI_ASSERT(step >= 0);
399  if (step >= steps_.size())
400  return false;
401  const StepInfo &step_info = steps_[step];
402  const NetworkNode &node = nnet_.GetNode(step_info.node_index);
403  return (node.node_type == kInput);
404 }
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:153
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void OutputDebugInfo ( NnetComputation computation) const
private

Definition at line 1346 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().

1346  {
1347  int32 num_matrices = computation->matrices.size(),
1348  num_steps = steps_.size();
1349  computation->matrix_debug_info.resize(num_matrices);
1350  for (int32 step = 0; step < num_steps; step++) {
1351  const StepInfo &step_info = steps_[step];
1352  if (step_info.value == 0)
1353  continue; // e.g. input step for ConstantComponent.
1354  if (!computation->IsWholeMatrix(step_info.value))
1355  continue;
1356  int32 value_matrix = computation->submatrices[step_info.value].matrix_index;
1357  int32 deriv_matrix = 0;
1358  if (step_info.deriv != 0 && computation->IsWholeMatrix(step_info.deriv))
1359  deriv_matrix = computation->submatrices[step_info.deriv].matrix_index;
1360 
1361  NnetComputation::MatrixDebugInfo &debug_info =
1362  computation->matrix_debug_info[value_matrix];
1363  debug_info.is_deriv = false;
1364  AppendCindexes(step_info.node_index, step_info.output_indexes,
1365  &debug_info.cindexes);
1366  if (deriv_matrix != 0) {
1367  NnetComputation::MatrixDebugInfo &deriv_debug_info =
1368  computation->matrix_debug_info[deriv_matrix];
1369  deriv_debug_info.is_deriv = true;
1370  deriv_debug_info.cindexes = debug_info.cindexes;
1371  }
1372  }
1373 }
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:153
void SetUpPrecomputedIndexes ( const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

Definition at line 1239 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().

1241  {
1242  int32 num_steps = steps_.size();
1243  KALDI_ASSERT(computation->component_precomputed_indexes.empty());
1244  // the zeroth commponent is special, contains a NULL pointer.
1245  computation->component_precomputed_indexes.resize(1);
1246  for (int32 step = 0; step < num_steps; step++) {
1247  StepInfo &step_info = steps_[step];
1248  int32 node_index = step_info.node_index;
1249  const NetworkNode &node = nnet_.GetNode(node_index);
1250  // There is only something to do for nodes of type Component.
1251  if (node.node_type != kComponent)
1252  continue;
1253  const StepInfo &input_step_info = steps_[step - 1];
1254  int32 component_index = node.u.component_index;
1255  int32 input_node_index = input_step_info.node_index;
1256  KALDI_ASSERT(input_node_index == node_index - 1);
1257  const std::vector<Index> &input_indexes = input_step_info.output_indexes;
1258  const std::vector<Index> &output_indexes = step_info.output_indexes;
1259 
1260  const Component *component = nnet_.GetComponent(component_index);
1261 
1262  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1263  bool need_derivs = request.NeedDerivatives();
1264  ComponentPrecomputedIndexes *precomputed_indexes =
1265  component->PrecomputeIndexes(request.misc_info,
1266  input_indexes, output_indexes,
1267  need_derivs);
1268  if (precomputed_indexes == NULL) {
1269  // e.g. simple Components, and some other Components, will return NULL for
1270  // precomputed_indexes.
1271  step_info.precomputed_indexes_index = 0;
1272  } else {
1273  step_info.precomputed_indexes_index =
1274  computation->component_precomputed_indexes.size();
1275 
1276  NnetComputation::PrecomputedIndexesInfo info;
1277  info.data = precomputed_indexes;
1278 
1279  if (!input_indexes.empty() && input_indexes.back().n == 1 &&
1280  !output_indexes.empty() && output_indexes.back().n == 1) {
1281  // If these conditions are true, it's *possible* that we are doing
1282  // 'shortcut' compilation. So just in case that's what's going on, we
1283  // store 'input_indexes' and 'output_indexes, which are needed by
1284  // the ExpandComputation() function that is used in that process.
1285  info.input_indexes = input_indexes;
1286  info.output_indexes = output_indexes;
1287  }
1288  computation->component_precomputed_indexes.push_back(info);
1289  }
1290  }
1291 }
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:153
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 557 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().

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