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 DoForwardComputation (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 DoForwardComputationDescriptor (int32 step, NnetComputation *computation) const
 
void DoForwardComputationSumDescriptor (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
 
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 DoForwardComputationFromSubmatLocationsList (int32 value_submatrix_index, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
 
void DoForwardComputationFromSubmatLocations (int32 value_submatrix_index, bool is_first_term_in_sum, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
 
void DoForwardComputationFromIndexes (int32 value_submatrix_index, int32 input_submatrix_index, bool is_first_term_in_sum, const std::vector< int32 > &indexes, NnetComputation *computation) const
 
void DoBackwardComputation (int32 step, NnetComputation *computation)
 
void AddBackwardStepComponent (int32 step, NnetComputation *computation) const
 
void AddBackwardStepInput (int32 step, NnetComputation *computation) const
 
void DoBackwardComputationDescriptor (int32 step, NnetComputation *computation)
 
void DoBackwardComputationSumDescriptor (int32 step, int32 part_index, NnetComputation *computation) const
 
void DoBackwardComputationFromSubmatLocationsList (int32 deriv_submatrix_index, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
 
void DoBackwardComputationFromSubmatLocations (int32 deriv_submatrix_index, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
 
void DoBackwardComputationFromIndexes (int32 deriv_submatrix_index, int32 input_deriv_submatrix_index, 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 928 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::DoBackwardComputation().

929  {
930  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
931  const StepInfo &step_info = steps_[step];
932  int32 input_step = step - 1;
933  const StepInfo &input_step_info = steps_[input_step];
934  int32 node_index = step_info.node_index;
935  const NetworkNode &node = nnet_.GetNode(node_index);
936  KALDI_ASSERT(node.node_type == kComponent);
937  int32 component_index = node.u.component_index;
938  const Component *component = nnet_.GetComponent(component_index);
939  int32 properties = component->Properties();
940 
941  int32 input_submatrix_index = input_step_info.value,
942  output_submatrix_index = step_info.value,
943  input_deriv_submatrix_index = input_step_info.deriv,
944  output_deriv_submatrix_index = step_info.deriv,
945  memo_index = (properties & kUsesMemo ? step : 0);
946  KALDI_ASSERT(output_deriv_submatrix_index > 0 &&
947  (input_deriv_submatrix_index > 0 ||
948  properties & kUpdatableComponent));
949 
950  if (! (properties & kBackpropNeedsInput))
951  input_submatrix_index = 0;
952  if (! (properties & kBackpropNeedsOutput))
953  output_submatrix_index = 0;
954 
955  NnetComputation::Command c(kBackprop,
956  component_index,
957  step_info.precomputed_indexes_index,
958  input_submatrix_index,
959  output_submatrix_index,
960  output_deriv_submatrix_index,
961  input_deriv_submatrix_index,
962  memo_index);
963  computation->commands.push_back(c);
964 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
virtual int32 Properties() const =0
Return bitmask of the component's properties.
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddBackwardStepInput ( int32  step,
NnetComputation computation 
) const
private

Definition at line 910 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::DoBackwardComputation().

911  {
912  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
913  const StepInfo &step_info = steps_[step];
914  int32 node_index = step_info.node_index,
915  deriv_submatrix_index = step_info.deriv;
916  if (deriv_submatrix_index == 0)
917  return; // Nothing to do.
918  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
919  const NetworkNode &node = nnet_.GetNode(node_index);
920  // actually, currently the node type would always be kInput.
921  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
922 
923  NnetComputation::Command c(kProvideOutput, deriv_submatrix_index, node_index);
924  computation->commands.push_back(c);
925 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddCommands ( const std::vector< bool > &  deriv_needed,
const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

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

References Compiler::AllocateMatrices(), NnetComputation::commands, Compiler::DeallocateMatrices(), Compiler::DoBackwardComputation(), Compiler::DoForwardComputation(), 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  DoForwardComputation(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  DoBackwardComputation(step, computation);
137 
138  DeallocateMatrices(whole_submatrices, step_to_segment, computation);
139 }
void DoForwardComputation(int32 step, NnetComputation *computation) const
void DoBackwardComputation(int32 step, NnetComputation *computation)
void SetUpPrecomputedIndexes(const std::vector< int32 > &step_to_segment, NnetComputation *computation)
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
void DeallocateMatrices(const std::vector< int32 > &whole_submatrices, const std::vector< int32 > &step_to_segment, NnetComputation *computation)
void AllocateMatrices(const std::vector< int32 > &whole_submatrices, NnetComputation *computation) const
void AddForwardStepComponent ( int32  step,
NnetComputation computation 
) const
private

Definition at line 876 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::DoForwardComputation().

877  {
878  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
879  const StepInfo &step_info = steps_[step];
880  int32 input_step = step - 1;
881  const StepInfo &input_step_info = steps_[input_step];
882  int32 node_index = step_info.node_index;
883  const NetworkNode &node = nnet_.GetNode(node_index);
884  KALDI_ASSERT(node.node_type == kComponent);
885  int32 component_index = node.u.component_index;
886  const Component *component = nnet_.GetComponent(component_index);
887 
888  // note RE memo_index: we'll renumber them in optimization to get rid of gaps.
889  // The use of 'step' as the memo index is OK because step > 0 if we're doing
890  // forward propagation, there must be preceding steps for inputs or for
891  // component-input nodes).
892  int32 properties = component->Properties(),
893  input_submatrix_index = input_step_info.value,
894  output_submatrix_index = step_info.value,
895  memo_index = (step_info.deriv > 0 && (properties & kUsesMemo) ? step : 0),
896  store_stats = (requests_[0]->store_component_stats &&
897  (properties & kStoresStats) ? 1 : 0);
898 
899  NnetComputation::Command c(kPropagate,
900  component_index,
901  step_info.precomputed_indexes_index,
902  input_submatrix_index,
903  output_submatrix_index,
904  memo_index,
905  store_stats);
906  computation->commands.push_back(c);
907 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
virtual int32 Properties() const =0
Return bitmask of the component's properties.
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AddForwardStepInput ( int32  step,
NnetComputation computation 
) const
private

Definition at line 859 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::DoForwardComputation().

860  {
861  KALDI_ASSERT(static_cast<size_t>(step) < steps_.size());
862  const StepInfo &step_info = steps_[step];
863  int32 node_index = step_info.node_index,
864  submatrix_index = step_info.value;
865  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
866 
867  const NetworkNode &node = nnet_.GetNode(node_index);
868  // actually currently the node type would always be kInput.
869  KALDI_ASSERT(node.node_type == kInput || node.node_type == kComponent);
870 
871  NnetComputation::Command c(kAcceptInput, submatrix_index, node_index);
872  computation->commands.push_back(c);
873 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void AllocateMatrices ( const std::vector< int32 > &  whole_submatrices,
NnetComputation computation 
) const
private

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

References NnetComputation::commands, Compiler::StepInfo::deriv, Compiler::graph_, ComputationGraph::is_input, Nnet::IsOutputNode(), KALDI_ASSERT, kaldi::nnet3::kAllocMatrixZeroed, 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().

969  {
970  KALDI_ASSERT(computation->commands.empty());
971  // Work out which matrices are inputs to the computation (or output-derivs,
972  // which are also supplied as inputs to the computation); we won't be setting
973  // these up.
974  unordered_set<int32> input_and_oderiv_matrices;
975  int32 num_steps = steps_.size();
976  for (int32 step = 0; step < num_steps; step++) {
977  const StepInfo &this_info = steps_[step];
978  if (this_info.output_cindex_ids.empty())
979  continue;
980  int32 first_cindex_id = this_info.output_cindex_ids.front(),
981  node_index = this_info.node_index;
982  bool is_input = graph_.is_input[first_cindex_id],
983  is_output = nnet_.IsOutputNode(node_index);
984  if (is_input) {
985  int32 value_submatrix_index = this_info.value,
986  value_matrix_index =
987  computation->submatrices[value_submatrix_index].matrix_index;
988  input_and_oderiv_matrices.insert(value_matrix_index);
989  }
990  if (is_output && this_info.deriv != 0) {
991  int32 deriv_submatrix_index = this_info.deriv,
992  deriv_matrix_index =
993  computation->submatrices[deriv_submatrix_index].matrix_index;
994  input_and_oderiv_matrices.insert(deriv_matrix_index);
995  }
996  }
997 
998  int32 num_matrices = computation->matrices.size();
999  for (int32 m = 1; m < num_matrices; m++) {
1000  // Later in the optimization phase, it turns out that zeroing is not
1001  // necessary for some matrices, we'll turn these commands into
1002  // kAllocMatrixUndefined.
1003  // We don't set up the matrices that are inputs to the computation;
1004  // this happens when the user provides the input.
1005  if (input_and_oderiv_matrices.count(m) == 0) {
1006  // get a submatrix index that refers to the entire matrix.
1007  int32 submatrix_index = whole_submatrices[m];
1008  NnetComputation::Command c(kAllocMatrixZeroed, submatrix_index);
1009  computation->commands.push_back(c);
1010  }
1011  }
1012 }
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
ComputationGraph graph_
Definition: nnet-compile.h:64
std::vector< bool > is_input
For each Cindex this tells us whether it was provided as an input to the network. ...
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void 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 517 of file nnet-compile.cc.

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

Referenced by Compiler::DoBackwardComputationSumDescriptor().

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

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

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

Referenced by Compiler::CreateStepInfo().

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

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

Referenced by Compiler::DoForwardComputationSumDescriptor().

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

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

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

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

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

Referenced by Compiler::CreateComputation().

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

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

1071  {
1072  // This adds the commands to destroy all the matrices- but not the
1073  // ones that might be needed as outputs of the computation. The ones that
1074  // are spared from destruction are those corresponding to outputs of the
1075  // computation, and those corresponding to input derivatives that were
1076  // requested by the user.
1077  int32 num_matrices = computation->matrices.size();
1078  std::vector<bool> will_destroy(num_matrices, true);
1079 
1080  int32 num_steps = steps_.size();
1081  for (int32 step = 0; step < num_steps; step++) {
1082  const StepInfo &step_info = steps_[step];
1083  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1084  if (nnet_.IsOutputNode(step_info.node_index)) {
1085  // steps corresponding to output nodes need to have their "value" kept.
1086  int32 value_matrix_index =
1087  computation->submatrices[step_info.value].matrix_index;
1088  will_destroy[value_matrix_index] = false;
1089  } else if (nnet_.IsInputNode(step_info.node_index)) {
1090  // steps corresponding to input nodes need to have their "deriv" kept, but
1091  // only if the corresponding input derivative was requested. (we don't
1092  // need to worry about whether outputs were requested, because if they
1093  // were not requested we would not be computing them in the first place).
1094  std::string input_name = nnet_.GetNodeNames()[step_info.node_index];
1095  int32 i = 0, num_inputs = request.inputs.size();
1096  bool has_deriv = false;
1097  for (; i < num_inputs; i++) {
1098  if (input_name == request.inputs[i].name) {
1099  has_deriv = request.inputs[i].has_deriv;
1100  break;
1101  }
1102  }
1103  KALDI_ASSERT(i != num_inputs); // assert we found an input-request with
1104  // this name
1105  if (has_deriv) {
1106  int32 deriv_matrix_index =
1107  computation->submatrices[step_info.deriv].matrix_index;
1108  will_destroy[deriv_matrix_index] = false;
1109  }
1110  }
1111  }
1112  // note: matrix-index 0 is the empty matrix.
1113  for (int32 m = 1; m < num_matrices; m++) {
1114  if (will_destroy[m]) {
1115  int32 submatrix_index = whole_submatrices[m];
1116  computation->commands.push_back(
1117  NnetComputation::Command(kDeallocMatrix, submatrix_index));
1118  }
1119  }
1120 }
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
Definition: nnet-nnet.cc:120
const std::vector< std::string > & GetNodeNames() const
returns vector of node names (needed by some parsing code, for instance).
Definition: nnet-nnet.cc:63
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void DefineMatrices ( NnetComputation computation) const
private
void DefineSubmatrices ( NnetComputation computation)
private
void DoBackwardComputation ( int32  step,
NnetComputation computation 
)
private

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

References Compiler::AddBackwardStepComponent(), Compiler::AddBackwardStepInput(), NnetComputation::commands, Compiler::DoBackwardComputationDescriptor(), 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().

830  {
831  KALDI_ASSERT(step < static_cast<int32>(steps_.size()));
832  const StepInfo &step_info = steps_[step];
833  int32 node_index = step_info.node_index;
834  const NetworkNode &node = nnet_.GetNode(node_index);
835 
836  switch (node.node_type) {
837  case kInput:
838  AddBackwardStepInput(step, computation);
839  if (!IsInputStep(step + 1)) // Make sure backward computation is nonempty.
840  computation->commands.push_back(
841  NnetComputation::Command(kNoOperationPermanent));
842  break;
843  case kDimRange:
844  break; // Nothing to do.
845  case kComponent:
846  AddBackwardStepComponent(step, computation);
847  break;
848  case kDescriptor:
849  DoBackwardComputationDescriptor(step, computation);
850  break;
851  default:
852  KALDI_ERR << "Invalid node type";
853  }
854 }
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 AddBackwardStepInput(int32 step, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void DoBackwardComputationDescriptor(int32 step, NnetComputation *computation)
void AddBackwardStepComponent(int32 step, NnetComputation *computation) const
void DoBackwardComputationDescriptor ( int32  step,
NnetComputation computation 
)
private

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

References NnetComputation::commands, Compiler::StepInfo::deriv, Compiler::DoBackwardComputationSumDescriptor(), 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::DoBackwardComputation().

809  {
810  StepInfo &step_info = steps_[step];
811  if (nnet_.IsOutputNode(step_info.node_index) &&
812  step_info.deriv > 0) {
813  int32 deriv_submatrix_index = step_info.deriv;
814  KALDI_ASSERT(computation->IsWholeMatrix(deriv_submatrix_index));
815  NnetComputation::Command c(kAcceptInput, deriv_submatrix_index,
816  step_info.node_index);
817  computation->commands.push_back(c);
818  }
819 
820  // the top-level descriptor has a bunch of parts that we concatenate features
821  // over.
822  int32 num_parts = step_info.value_parts.size();
823  for (int32 part = 0; part < num_parts; part++)
825  computation);
826 }
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 DoBackwardComputationSumDescriptor(int32 step, int32 part_index, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void DoBackwardComputationFromIndexes ( int32  deriv_submatrix_index,
int32  input_deriv_submatrix_index,
const std::vector< int32 > &  indexes,
NnetComputation computation 
) const
private

Definition at line 722 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::DoBackwardComputationFromSubmatLocations().

726  {
727 
728  int32 num_rows = computation->submatrices[deriv_submatrix_index].num_rows,
729  input_num_rows =
730  computation->submatrices[input_deriv_submatrix_index].num_rows;
731  KALDI_ASSERT(indexes.size() == num_rows);
732  if (input_num_rows == num_rows) {
733  int32 i;
734  for (i = 0; i < num_rows; i++)
735  if (indexes[i] != i)
736  break;
737  if (i == num_rows) { // Simplest case: just matrix addition.
738  computation->commands.push_back(
739  NnetComputation::Command(kMatrixAdd,
740  input_deriv_submatrix_index,
741  deriv_submatrix_index));
742 
743  return;
744  }
745  }
746  if (input_num_rows >= num_rows) {
747  // If there are no repeated elements in the "indexes" array, we can reverse
748  // the mapping and make it an operation of type kAddRows. TODO: change this
749  // to use kAddToRows, kCopyToRows, when implemented (will be more
750  // efficient).
751  std::vector<int32> reverse_indexes(input_num_rows, -1);
752  int32 i;
753  for (i = 0; i < num_rows; i++) {
754  int32 index_i = indexes[i];
755  KALDI_ASSERT(index_i >= -1 && index_i < input_num_rows);
756  if (index_i >= 0) {
757  if (reverse_indexes[index_i] == -1)
758  reverse_indexes[index_i] = i;
759  else
760  break;
761  } // note: there may be -1's in 'indexes', meaning just use zero.
762  }
763  if (i == num_rows) {
764  // There were no repeated elements, and this strategy will work.
765  int32 indexes_index = computation->indexes.size();
766  computation->indexes.push_back(reverse_indexes);
767  computation->commands.push_back(
768  NnetComputation::Command(kAddRows,
769  input_deriv_submatrix_index,
770  deriv_submatrix_index,
771  indexes_index));
772  return;
773  }
774  }
775  std::vector<std::pair<int32, int32> > ranges;
776  if (HasContiguousProperty(indexes, &ranges)) {
777  // the operation can be set up as AddRowRanges.
778  if (static_cast<int32>(ranges.size()) != input_num_rows) {
779  KALDI_ASSERT(static_cast<int32>(ranges.size()) < input_num_rows);
780  // extend with (-1, -1) pairs.
781  ranges.resize(input_num_rows, std::pair<int32,int32>(-1, -1));
782  }
783  int32 indexes_ranges_index = computation->indexes_ranges.size();
784  computation->indexes_ranges.push_back(ranges);
785  computation->commands.push_back(
786  NnetComputation::Command(kAddRowRanges,
787  input_deriv_submatrix_index,
788  deriv_submatrix_index,
789  indexes_ranges_index));
790  // TODO: if any of these ranges are quite long (summing over many rows), the
791  // resulting code could be inefficient because the AddRowRanges kernels
792  // takes time linear in the length of the range. Using a temporary matrix
793  // with an intermediate size would make this more efficient in that case, so
794  // the one command would be two commands (plus commands to set up and
795  // destroy the temporary matrix).
796  return;
797  }
798 
799  // If you ever reach here, it means someone has used a type of network that we
800  // don't yet support in the backprop. Basically this case can be handled by
801  // creating a temporary matrix to reorder the matrix at deriv_submatrix_index,
802  // (using CopyRows), and doing AddRowRanges from that.
803  // It wouldn't be too much work.
804  KALDI_ERR << "This case not implemented yet.";
805 }
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 DoBackwardComputationFromSubmatLocations ( int32  deriv_submatrix_index,
const std::vector< std::pair< int32, int32 > > &  submat_locations,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::DoBackwardComputationFromSubmatLocationsList().

676  {
677  // This function creates a command to handle an individual piece of the
678  // Descriptor, for backprop. Note: because the backprop case is a little
679  // trickier to implement efficiently on the GPU, there may be cases
680  // which we will refuse to implement backprop for if we get here.
681 
682 
683 
684  int32 first_value;
685  std::vector<int32> second_values;
686  if (ConvertToIndexes(submat_locations, &first_value,
687  &second_values)) {
688  int32 input_deriv_submatrix_index = first_value;
689  DoBackwardComputationFromIndexes(deriv_submatrix_index,
690  input_deriv_submatrix_index,
691  second_values,
692  computation);
693  return;
694  } else {
695  // There are multiple source matrices.
696  std::vector<std::pair<int32, int32> > submat_locations_sorted;
697  std::sort(submat_locations_sorted.begin(), submat_locations_sorted.end());
698  if (IsSortedAndUniq(submat_locations_sorted)) {
699  // There are no repeats in any of the submat locations. This means that
700  // we can just use kAddToRowsMulti (i.e. AddToRows with pointer
701  // destination). If there were repeats, the CUDA kernel would require
702  // special synchronization so we don't allow it.
703  int32 indexes_multi_index = computation->indexes_multi.size();
704  computation->indexes_multi.push_back(submat_locations);
705  computation->commands.push_back(
706  NnetComputation::Command(kAddToRowsMulti,
707  deriv_submatrix_index,
708  indexes_multi_index));
709  return;
710  }
711  // If you reach this point, there is a case that wasn't handled. Our
712  // intended strategy to handle it, if it's ever needed, is to create a
713  // temporary matrix consisting of all the unique submat_locations in the
714  // input. We would first recurse to DoBackwardComputationFromIndexes, and
715  // let it write to this temporary matrix; and then do the kAddToRowsMulti
716  // command as above to go from the temporary matrix to the multiple
717  // matrices.
718  KALDI_ERR << "This case not handled.";
719  }
720 }
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 DoBackwardComputationFromIndexes(int32 deriv_submatrix_index, int32 input_deriv_submatrix_index, 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 DoBackwardComputationFromSubmatLocationsList ( int32  deriv_submatrix_index,
const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_locations,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::DoBackwardComputationSumDescriptor().

645  {
646  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
647  SplitLocationsBackward(submat_lists, &split_lists);
648  int32 size = split_lists.size(); // size may be zero e.g. for unused outputs.
649  for (int32 i = 0; i < size; i++)
651  deriv_submatrix_index,
652  split_lists[i],
653  computation);
654 }
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 DoBackwardComputationFromSubmatLocations(int32 deriv_submatrix_index, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
void DoBackwardComputationSumDescriptor ( int32  step,
int32  part_index,
NnetComputation computation 
) const
private

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

References Compiler::ComputeDerivSubmatLocationsList(), Compiler::StepInfo::deriv_parts, Compiler::DoBackwardComputationFromSubmatLocationsList(), Compiler::StepInfo::input_locations_list, KALDI_ASSERT, and Compiler::steps_.

Referenced by Compiler::DoBackwardComputationDescriptor().

658  {
659  const StepInfo &step_info = steps_[step];
660  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
661  ComputeDerivSubmatLocationsList(step_info.input_locations_list[part_index],
662  &submat_locations_list);
663  int32 deriv_submatrix_index = step_info.deriv_parts[part_index];
664  KALDI_ASSERT(deriv_submatrix_index > 0); // or should not have called this.
665 
666  DoBackwardComputationFromSubmatLocationsList(deriv_submatrix_index,
667  submat_locations_list,
668  computation);
669 }
void DoBackwardComputationFromSubmatLocationsList(int32 deriv_submatrix_index, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void ComputeDerivSubmatLocationsList(const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
void DoForwardComputation ( int32  step,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::AddCommands().

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

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

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

Referenced by Compiler::DoForwardComputation().

418  {
419  int32 num_parts = steps_[step].value_parts.size();
420  for (int32 part = 0; part < num_parts; part++)
421  DoForwardComputationSumDescriptor(step, part, computation);
422  const StepInfo &step_info = steps_[step];
423  if (nnet_.IsOutputNode(step_info.node_index)) {
424  // If the node is an output then we need to add commands to provide the
425  // output to the user, and possibly to get derivatives w.r.t. the output
426  // from the user.
427  int32 node_index = step_info.node_index,
428  submatrix_index = step_info.value;
429  KALDI_ASSERT(computation->IsWholeMatrix(submatrix_index));
430  NnetComputation::Command c(kProvideOutput, submatrix_index, node_index);
431  computation->commands.push_back(c);
432  }
433 }
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void DoForwardComputationSumDescriptor(int32 step, int32 part_index, NnetComputation *computation) const
void DoForwardComputationFromIndexes ( int32  value_submatrix_index,
int32  input_submatrix_index,
bool  is_first_term_in_sum,
const std::vector< int32 > &  indexes,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::DoForwardComputationFromSubmatLocations().

560  {
561 
562  int32 input_num_rows =
563  computation->submatrices[input_submatrix_index].num_rows,
564  num_rows = indexes.size();
565  if (input_num_rows == num_rows) {
566  int32 i;
567  for (i = 0; i < num_rows; i++)
568  if (indexes[i] != i)
569  break;
570  if (i == num_rows) { // Simplest case: just matrix addition.
571  CommandType ctype =
572  (is_first_term_in_sum ?
574  computation->commands.push_back(
575  NnetComputation::Command(ctype, value_submatrix_index,
576  input_submatrix_index));
577 
578  return;
579  }
580  }
581  // if we got to here, it's not just a case of matrix-copy or matrix-add,
582  // but it's still from a single source matrix.
583  int32 indexes_index = computation->indexes.size();
584  computation->indexes.push_back(indexes);
585  CommandType ctype =
586  (is_first_term_in_sum ?
587  kCopyRows : kAddRows);
588  computation->commands.push_back(
589  NnetComputation::Command(ctype, value_submatrix_index,
590  input_submatrix_index, indexes_index));
591  return;
592 }
CommandType
CommandType is an enum that describes the category of the command used in the NnetComputation.
void DoForwardComputationFromSubmatLocations ( int32  value_submatrix_index,
bool  is_first_term_in_sum,
const std::vector< std::pair< int32, int32 > > &  submat_locations,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::DoForwardComputationFromSubmatLocationsList().

598  {
599 
600 
601  int32 input_submatrix_index = -1;
602  std::vector<int32> indexes;
603 
604  if (ConvertToIndexes(submat_locations, &input_submatrix_index, &indexes)) {
605  DoForwardComputationFromIndexes(value_submatrix_index,
606  input_submatrix_index,
607  is_first_term_in_sum,
608  indexes,
609  computation);
610  return;
611  } else {
612  // There are multiple source matrices.
613  CommandType ctype =
614  (is_first_term_in_sum ?
616  int32 indexes_multi_index = computation->indexes_multi.size();
617  computation->indexes_multi.push_back(submat_locations);
618  computation->commands.push_back(
619  NnetComputation::Command(ctype, value_submatrix_index,
620  indexes_multi_index));
621  return;
622  }
623 }
CommandType
CommandType is an enum that describes the category of the command used in the NnetComputation.
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 DoForwardComputationFromIndexes(int32 value_submatrix_index, int32 input_submatrix_index, bool is_first_term_in_sum, const std::vector< int32 > &indexes, NnetComputation *computation) const
void DoForwardComputationFromSubmatLocationsList ( int32  value_submatrix_index,
const std::vector< std::vector< std::pair< int32, int32 > > > &  submat_locations,
NnetComputation computation 
) const
private

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

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

Referenced by Compiler::DoForwardComputationSumDescriptor().

628  {
629  std::vector<std::vector<std::pair<int32, int32> > > split_lists;
630  SplitLocations(submat_lists, &split_lists);
631  int32 size = split_lists.size();
632  // note: size may be empty in unusual cases so don't assert that it's
633  // nonzero.
634  for (int32 i = 0; i < size; i++)
636  value_submatrix_index, (i == 0),
637  split_lists[i],
638  computation);
639 }
void DoForwardComputationFromSubmatLocations(int32 value_submatrix_index, bool is_first_term_in_sum, const std::vector< std::pair< int32, int32 > > &submat_locations, NnetComputation *computation) const
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 DoForwardComputationSumDescriptor ( int32  step,
int32  part_index,
NnetComputation computation 
) const
private

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

References Compiler::ComputeValueSubmatLocationsList(), Compiler::DoForwardComputationFromSubmatLocationsList(), Compiler::StepInfo::input_locations_list, Compiler::steps_, and Compiler::StepInfo::value_parts.

Referenced by Compiler::DoForwardComputationDescriptor().

543  {
544  const StepInfo &step_info = steps_[step];
545  std::vector<std::vector<std::pair<int32, int32> > > submat_locations_list;
546  ComputeValueSubmatLocationsList(step_info.input_locations_list[part_index],
547  &submat_locations_list);
548  int32 value_submatrix_index = step_info.value_parts[part_index];
550  value_submatrix_index,
551  submat_locations_list,
552  computation);
553 }
void DoForwardComputationFromSubmatLocationsList(int32 value_submatrix_index, const std::vector< std::vector< std::pair< int32, int32 > > > &submat_locations, NnetComputation *computation) const
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void ComputeValueSubmatLocationsList(const std::vector< std::vector< std::pair< int32, int32 > > > &input_locations_list, std::vector< std::vector< std::pair< int32, int32 > > > *submat_locations_list) const
MatrixStrideType GetStrideType ( int32  node_index) const
private

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

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

Referenced by Compiler::CreateStepInfo().

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

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

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

Referenced by Compiler::DoBackwardComputation(), and Compiler::DoForwardComputation().

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

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

1122  {
1123  int32 num_matrices = computation->matrices.size(),
1124  num_steps = steps_.size();
1125  computation->matrix_debug_info.resize(num_matrices);
1126  for (int32 step = 0; step < num_steps; step++) {
1127  const StepInfo &step_info = steps_[step];
1128  if (step_info.value == 0)
1129  continue; // e.g. input step for ConstantComponent.
1130  if (!computation->IsWholeMatrix(step_info.value))
1131  continue;
1132  int32 value_matrix = computation->submatrices[step_info.value].matrix_index;
1133  int32 deriv_matrix = 0;
1134  if (step_info.deriv != 0 && computation->IsWholeMatrix(step_info.deriv))
1135  deriv_matrix = computation->submatrices[step_info.deriv].matrix_index;
1136 
1137  NnetComputation::MatrixDebugInfo &debug_info =
1138  computation->matrix_debug_info[value_matrix];
1139  debug_info.is_deriv = false;
1140  AppendCindexes(step_info.node_index, step_info.output_indexes,
1141  &debug_info.cindexes);
1142  if (deriv_matrix != 0) {
1143  NnetComputation::MatrixDebugInfo &deriv_debug_info =
1144  computation->matrix_debug_info[deriv_matrix];
1145  deriv_debug_info.is_deriv = true;
1146  deriv_debug_info.cindexes = debug_info.cindexes;
1147  }
1148  }
1149 }
void AppendCindexes(int32 node, const std::vector< Index > &indexes, std::vector< Cindex > *out)
Appends to 'out' the pairs (node, indexes[0]), (node, indexes[1]), ...
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
void SetUpPrecomputedIndexes ( const std::vector< int32 > &  step_to_segment,
NnetComputation computation 
)
private

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

1017  {
1018  int32 num_steps = steps_.size();
1019  KALDI_ASSERT(computation->component_precomputed_indexes.empty());
1020  // the zeroth commponent is special, contains a NULL pointer.
1021  computation->component_precomputed_indexes.resize(1);
1022  for (int32 step = 0; step < num_steps; step++) {
1023  StepInfo &step_info = steps_[step];
1024  int32 node_index = step_info.node_index;
1025  const NetworkNode &node = nnet_.GetNode(node_index);
1026  // There is only something to do for nodes of type Component.
1027  if (node.node_type != kComponent)
1028  continue;
1029  const StepInfo &input_step_info = steps_[step - 1];
1030  int32 component_index = node.u.component_index;
1031  int32 input_node_index = input_step_info.node_index;
1032  KALDI_ASSERT(input_node_index == node_index - 1);
1033  const std::vector<Index> &input_indexes = input_step_info.output_indexes;
1034  const std::vector<Index> &output_indexes = step_info.output_indexes;
1035 
1036  const Component *component = nnet_.GetComponent(component_index);
1037 
1038  const ComputationRequest &request = *(requests_[step_to_segment[step]]);
1039  bool need_derivs = request.NeedDerivatives();
1040  ComponentPrecomputedIndexes *precomputed_indexes =
1041  component->PrecomputeIndexes(request.misc_info,
1042  input_indexes, output_indexes,
1043  need_derivs);
1044  if (precomputed_indexes == NULL) {
1045  // e.g. simple Components, and some other Components, will return NULL for
1046  // precomputed_indexes.
1047  step_info.precomputed_indexes_index = 0;
1048  } else {
1049  step_info.precomputed_indexes_index =
1050  computation->component_precomputed_indexes.size();
1051 
1052  NnetComputation::PrecomputedIndexesInfo info;
1053  info.data = precomputed_indexes;
1054 
1055  if (!input_indexes.empty() && input_indexes.back().n == 1 &&
1056  !output_indexes.empty() && output_indexes.back().n == 1) {
1057  // If these conditions are true, it's *possible* that we are doing
1058  // 'shortcut' compilation. So just in case that's what's going on, we
1059  // store 'input_indexes' and 'output_indexes, which are needed by
1060  // the ExpandComputation() function that is used in that process.
1061  info.input_indexes = input_indexes;
1062  info.output_indexes = output_indexes;
1063  }
1064  computation->component_precomputed_indexes.push_back(info);
1065  }
1066  }
1067 }
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
Definition: nnet-nnet.h:146
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
virtual ComponentPrecomputedIndexes * PrecomputeIndexes(const MiscComputationInfo &misc_info, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, bool need_backprop) const
This function must return NULL for simple Components.
std::vector< StepInfo > steps_
Definition: nnet-compile.h:151
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169

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. A location is a pair (step-index, matrix-row-index).

Definition at line 158 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: