nnet-compute.cc
Go to the documentation of this file.
1 // nnet3/nnet-compute.cc
2 
3 // Copyright 2015 Johns Hopkins University (author: Daniel Povey)
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 #include <iterator>
21 #include <sstream>
22 #include "nnet3/nnet-compute.h"
23 
24 namespace kaldi {
25 namespace nnet3 {
26 
27 
29  const NnetComputation &computation,
30  const Nnet &nnet,
31  Nnet *nnet_to_update):
32  options_(options), computation_(computation), nnet_(nnet),
33  program_counter_(0), nnet_to_store_stats_(nnet_to_update),
34  nnet_to_update_(nnet_to_update) {
35  Init();
36 }
37 
39  const NnetComputation &computation,
40  Nnet *nnet,
41  Nnet *nnet_to_update):
42  options_(options), computation_(computation), nnet_(*nnet),
44  nnet_to_update_(nnet_to_update) {
45  Init();
46 }
47 
51  "You must call NnetComputation::ComputeCudaIndexes() before "
52  "executing the computation.");
53  matrices_.resize(computation_.matrices.size());
54  debug_ = (options_.debug || GetVerboseLevel() >= 5);
55  if (debug_) {
56  ComputationVariables variables;
57  variables.Init(computation_);
60  std::string preamble;
62  KALDI_LOG << preamble;
64  }
65 }
66 
67 //static
69  if (m.NumRows() == 0)
70  return 0.0;
71  return std::sqrt(TraceMatMat(m, m, kTrans) / (m.NumRows() * m.NumCols()));
72 }
73 
74 //static
76  const UpdatableComponent *uc = dynamic_cast<const UpdatableComponent*>(&c);
77  KALDI_ASSERT(uc != NULL &&
78  "Attempting to get parameter stddev of non-updatable component");
79  return std::sqrt(uc->DotProduct(*uc) / uc->NumParameters());
80 }
81 
83  CommandDebugInfo *info) {
84  {
85  const std::vector<int32> &matrices_written =
86  command_attributes_[command].matrices_written;
87  size_t size = matrices_written.size();
88  info->matrices_written_stddevs.resize(size);
89  for (size_t i = 0; i < size; i++) {
90  int32 m = matrices_written[i];
92  }
93  }
94  {
95  const std::vector<int32> &submatrices_written =
96  command_attributes_[command].submatrices_written;
97  size_t size = submatrices_written.size();
98  info->submatrices_written_stddevs.resize(size);
99  for (size_t i = 0; i < size; i++) {
100  int32 s = submatrices_written[i];
101  if (!computation_.IsWholeMatrix(s)) {
102  const CuSubMatrix<BaseFloat> submat(GetSubMatrix(s));
103  info->submatrices_written_stddevs[i] = MatrixStddev(submat);
104  }
105  }
106  }
107  const NnetComputation::Command &c = computation_.commands[command];
108  if (c.command_type == kBackprop) {
109  const Component *component = nnet_.GetComponent(c.arg1);
110  if (component->Properties() & kUpdatableComponent)
111  info->components_parameter_stddev = ParameterStddev(*component);
112  }
113 }
114 
115 
117  const CommandDebugInfo &info,
118  double command_exec_time) {
119  std::ostringstream os;
120  os << command_strings_[command] << "\t|\t";
121  {
122  const std::vector<int32> &matrices_written =
123  command_attributes_[command].matrices_written;
124  size_t size = matrices_written.size();
125  KALDI_ASSERT(info.matrices_written_stddevs.size() == size);
126  for (size_t i = 0; i < size; i++) {
127  int32 m = matrices_written[i];
128  BaseFloat old_stddev = info.matrices_written_stddevs[i],
129  stddev = MatrixStddev(matrices_[m]);
130  os << 'm' << m << ": " << old_stddev << "->" << stddev << " ";
131  }
132  }
133  {
134  const std::vector<int32> &submatrices_written =
135  command_attributes_[command].submatrices_written;
136  size_t size = submatrices_written.size();
137  KALDI_ASSERT(info.submatrices_written_stddevs.size() == size);
138  for (size_t i = 0; i < size; i++) {
139  int32 s = submatrices_written[i];
140  if (!computation_.IsWholeMatrix(s)) {
141  const CuSubMatrix<BaseFloat> submat(GetSubMatrix(s));
142  BaseFloat old_stddev = info.submatrices_written_stddevs[i],
143  stddev = MatrixStddev(submat);
144  os << submatrix_strings_[s] << ": " << old_stddev << "->"
145  << stddev << " ";
146  }
147  }
148  }
149  const NnetComputation::Command &c = computation_.commands[command];
150  if (c.command_type == kBackprop) {
151  const Component *component = nnet_.GetComponent(c.arg1);
152  if (component->Properties() & kUpdatableComponent) {
153  const std::string &component_name = nnet_.GetComponentName(c.arg1);
154  os << component_name << ": " << info.components_parameter_stddev
155  << "->" << ParameterStddev(*component) << " ";
156  }
157  }
158  os << "\t|\t time: " << command_exec_time << " secs";
159  KALDI_LOG << os.str();
160 }
161 
162 
164  const Component &c, void *memo) {
165  if (memo_index <= 0) {
166  if (memo != NULL) { // memo was returned but is not needed.
167  c.DeleteMemo(memo);
168  }
169  } else {
170  if (memos_.size() <= static_cast<size_t>(memo_index))
171  memos_.resize(memo_index + 1, NULL);
172  memos_[memo_index] = memo;
173  }
174 }
175 
176 void* NnetComputer::GetMemo(int32 memo_index) {
177  if (memo_index == 0) {
178  return NULL;
179  } else {
180  if (static_cast<size_t>(memo_index) >= memos_.size())
181  KALDI_ERR << "Memo requested that was not generated.";
182  void *ans = memos_[memo_index];
183  memos_[memo_index] = NULL;
184  return ans;
185  }
186 }
187 
188 
190  options_(other.options_),
191  computation_(other.computation_),
192  nnet_(other.nnet_),
197  debug_(other.debug_),
201  matrices_(other.matrices_),
202  memos_(other.memos_) {
203  // Note: this is the same as the default copy constructor, except for the check below.
204  if (!memos_.empty()) {
205  KALDI_ERR << "You cannot use the copy constructor of NnetComputer if "
206  "memos are used.";
207  }
208 }
209 
212  int32 m1, m2;
213  try {
214  switch (c.command_type) {
215  case kAllocMatrix:
216  m1 = computation_.submatrices[c.arg1].matrix_index;
217  matrices_[m1].Resize(computation_.matrices[m1].num_rows,
218  computation_.matrices[m1].num_cols,
219  kUndefined,
220  computation_.matrices[m1].stride_type);
221  break;
222  case kDeallocMatrix:
223  m1 = computation_.submatrices[c.arg1].matrix_index;
224  matrices_[m1].Resize(0, 0);
225  break;
226  case kSwapMatrix:
227  m1 = computation_.submatrices[c.arg1].matrix_index;
228  m2 = computation_.submatrices[c.arg2].matrix_index;
229  matrices_[m1].Swap(&(matrices_[m2]));
230  break;
231  case kSetConst: {
233  if (c.alpha == 0.0) s.SetZero();
234  else s.Set(c.alpha);
235  break;
236  }
237  case kPropagate: {
238  NVTX_RANGE("NnetComputer::ExecuteCommand::kPropagate");
239  const Component *component = nnet_.GetComponent(c.arg1);
240  ComponentPrecomputedIndexes *indexes =
242  const CuSubMatrix<BaseFloat> input(GetSubMatrix(c.arg3));
244  void *memo = component->Propagate(indexes, input, &output);
245  if (c.arg6) { // need to store stats.
247  Component *stats_component = nnet_to_store_stats_->GetComponent(c.arg1);
248  bool was_in_place = (c.arg3 == c.arg4);
249  // if propagate was in-place, provide empty matrix and not 'input', as
250  // input is no longer valid.
251  const CuSubMatrix<BaseFloat> maybe_input(
252  GetSubMatrix(was_in_place ? 0 : c.arg3));
253  stats_component->StoreStats(maybe_input, output, memo);
254  }
255  SaveMemo(c.arg5, *component, memo);
256  break;
257  }
258  case kBackprop:
259  case kBackpropNoModelUpdate: {
260  NVTX_RANGE("NnetComputer::ExecuteCommand::kBackpropNoModelUpdate");
261  std::ostringstream debug_str;
262  KALDI_ASSERT(nnet_to_update_ != NULL);
263  debug_str << nnet_.GetComponentName(c.arg1);
264  const Component *component = nnet_.GetComponent(c.arg1);
266  Component *upd_component = NULL;
267  if (c.command_type == kBackprop) { // this block sets 'upd_component'
268  Nnet *nnet_to_update;
269  if (component->Properties()&kUpdatableComponent) {
270  nnet_to_update = (computation_.need_model_derivative ?
271  nnet_to_update_ : NULL);
272  } else {
273  // Some non-updatable components, such as CompositeComponent, store
274  // stats in the backprop. For other types of non-updatable
275  // component, this arg won't matter.
276  nnet_to_update = nnet_to_store_stats_;
277  }
278  if (nnet_to_update)
279  upd_component = nnet_to_update->GetComponent(c.arg1);
280  }
281  ComponentPrecomputedIndexes *indexes =
283  const CuSubMatrix<BaseFloat> in_value(GetSubMatrix(c.arg3));
284  const CuSubMatrix<BaseFloat> out_value(GetSubMatrix(c.arg4));
285  const CuSubMatrix<BaseFloat> out_deriv(GetSubMatrix(c.arg5));
287  void *memo = GetMemo(c.arg7);
288  component->Backprop(debug_str.str(), indexes,
289  in_value, out_value, out_deriv,
290  memo, upd_component,
291  c.arg6 == 0 ? NULL : &in_deriv);
292  if (memo != NULL)
293  component->DeleteMemo(memo);
294  break;
295  }
296  case kMatrixCopy: {
299  dest.CopyFromMat(src);
300  if (c.alpha != 1.0)
301  dest.Scale(c.alpha); // note: in principle in future we could write a
302  // kernel which would do this in one operation.
303  break;
304  }
305  case kMatrixAdd: {
308  dest.AddMat(c.alpha, src);
309  break;
310  }
311  case kAddRows: {
314  const CuArray<int32> &indexes = computation_.indexes_cuda[c.arg3];
315  dest.AddRows(c.alpha, src, indexes);
316  break;
317  }
318  case kCopyRows: {
321  const CuArray<int32> &indexes = computation_.indexes_cuda[c.arg3];
322  BaseFloat alpha = c.alpha;
323  if (alpha != 1.0) { // for now we're faking the 'alpha' thing because the CopyRows
324  if (alpha == 0.0) break; // command doesn't take that argument.
325  dest.Scale(1.0 / alpha);
326  dest.CopyRows(src, indexes);
327  dest.Scale(c.alpha);
328  } else {
329  dest.CopyRows(src, indexes);
330  }
331  break;
332  }
333  case kCopyRowsMulti: {
335  CuArray<const BaseFloat*> pointers;
336  GetPointers(c.arg2, dest.NumCols(), &pointers);
337  BaseFloat alpha = c.alpha;
338  if (alpha != 1.0) { // for now we're faking the 'alpha' thing because the CopyRows
339  if (alpha == 0.0) break; // command doesn't take that argument.
340  dest.Scale(1.0 / alpha);
341  dest.CopyRows(pointers);
342  dest.Scale(c.alpha);
343  } else {
344  dest.CopyRows(pointers);
345  }
346  break;
347  }
348  case kCopyToRowsMulti: {
349  // If c.alpha is not 1.0, this command is not supported.
350  KALDI_ASSERT(c.alpha == 1.0);
352  CuArray<BaseFloat*> pointers;
353  GetPointers(c.arg2, src.NumCols(), &pointers);
354  src.CopyToRows(pointers);
355  break;
356  }
357  case kAddRowsMulti: {
359  CuArray<const BaseFloat*> pointers;
360  GetPointers(c.arg2, dest.NumCols(), &pointers);
361  dest.AddRows(c.alpha, pointers);
362  break;
363  }
364  case kAddToRowsMulti: {
366  CuArray<BaseFloat*> pointers;
367  GetPointers(c.arg2, src.NumCols(), &pointers);
368  src.AddToRows(c.alpha, pointers);
369  break;
370  }
371  case kAddRowRanges: {
375  BaseFloat alpha = c.alpha;
376  if (alpha != 1.0) { // for now we're faking the 'alpha' thing
377  // because the AddRowRanges
378  if (alpha == 0.0) break; // command doesn't take that argument.
379  dest.Scale(1.0 / alpha);
380  dest.AddRowRanges(src, pairs);
381  dest.Scale(c.alpha);
382  } else {
383  dest.AddRowRanges(src, pairs);
384  }
385  break;
386  }
387  case kCompressMatrix:
388  // This does nothing if CUDA is not in use.
389 #if HAVE_CUDA == 1
390  if (CuDevice::Instantiate().Enabled()) {
391  if (compressed_matrices_.empty())
392  compressed_matrices_.resize(matrices_.size(), NULL);
393  int32 m = computation_.submatrices[c.arg1].matrix_index;
394  KALDI_ASSERT(compressed_matrices_[m] == NULL &&
395  matrices_[m].NumRows() != 0);
396  BaseFloat range = c.alpha;
397  bool truncate = (c.arg3 != 0);
399  static_cast<CuCompressedMatrixType>(c.arg2),
400  range, truncate);
401  compressed_matrices_[m]->CopyFromMat(matrices_[m]);
402  matrices_[m].Resize(0, 0);
403  }
404 #endif
405  break;
406  case kDecompressMatrix:
407 #if HAVE_CUDA == 1
408  if (CuDevice::Instantiate().Enabled()) {
409  int32 m = computation_.submatrices[c.arg1].matrix_index;
410  CuCompressedMatrixBase *compressed_matrix =
412  KALDI_ASSERT(compressed_matrix != NULL &&
413  matrices_[m].NumRows() == 0);
414  matrices_[m].Resize(compressed_matrix->NumRows(),
415  compressed_matrix->NumCols(),
416  kUndefined,
417  computation_.matrices[m].stride_type);
418  compressed_matrix->CopyToMat(&(matrices_[m]));
419  delete compressed_matrix;
420  compressed_matrices_[m] = NULL;
421  }
422 #endif
423  break;
425  case kNoOperationLabel:
426  break;
427  case kGotoLabel:
430  break;
431  default:
432  KALDI_ERR << "Invalid command in computation";
433  }
434  } catch (...) {
435  if (!debug_) {
436  std::string preamble;
438  KALDI_WARN << "Printing some background info since error was detected";
439  KALDI_LOG << preamble;
440  for (int32 prev_c = 0; prev_c < program_counter_; prev_c++)
441  KALDI_LOG << command_strings_[prev_c];
442  }
443  // the following will re-throw the error, but now we've printed more info
444  // about what went wrong.
445  KALDI_ERR << "Error running command " << command_strings_[program_counter_];
446  }
447 }
448 
450  KALDI_PARANOID_ASSERT(static_cast<size_t>(submatrix_index) <
451  computation_.submatrices.size());
452  const NnetComputation::SubMatrixInfo &info =
453  computation_.submatrices[submatrix_index];
454  const CuMatrix<BaseFloat> &mat = matrices_[info.matrix_index];
455  return CuSubMatrix<BaseFloat>(
456  mat, info.row_offset, info.num_rows, info.col_offset, info.num_cols);
457 }
458 
459 void NnetComputer::GetPointers(int32 indexes_multi_index,
460  int32 num_cols,
461  CuArray<BaseFloat*> *pointers) {
462  KALDI_ASSERT(static_cast<size_t>(indexes_multi_index)
463  < computation_.indexes_multi.size());
464  const std::vector<std::pair<int32,int32> > &pairs =
465  computation_.indexes_multi[indexes_multi_index];
466  int32 size = pairs.size();
467  std::vector<BaseFloat*> vec(size);
468 
469  // the map "lookup" maps from submatrix index to the Data()
470  // pointer of that submatrix, and the corresponding Stride().
471  unordered_map<int32, std::pair<BaseFloat*, int32> > lookup;
472 
473  for (int32 i = 0; i < size; i++) {
474  int32 submatrix_index = pairs[i].first, row = pairs[i].second;
475  if (submatrix_index != -1) {
476  unordered_map<int32, std::pair<BaseFloat*, int32> >::iterator
477  iter = lookup.find(submatrix_index);
478  if (iter == lookup.end()) {
479  CuSubMatrix<BaseFloat> m = GetSubMatrix(submatrix_index);
480  lookup[submatrix_index] = std::pair<BaseFloat*, int32>(m.Data(),
481  m.Stride());
482  iter = lookup.find(submatrix_index);
483  }
484  BaseFloat *data = iter->second.first;
485  int32 stride = iter->second.second;
486  vec[i] = data + (row * stride);
487  } else {
488  // -1 is a marker that will be translated to NULL.
489  vec[i] = NULL;
490  }
491  }
492 #ifdef KALDI_PARANOID
493  for (int32 i = 0; i < size; i += 30 + RandInt(0, 9)) {
494  // Do a pseudo-random spot check that the row-indexes are not out of range.
495  int32 submatrix_index = pairs[i].first, row = pairs[i].second;
496  if (submatrix_index != -1) {
497  CuSubMatrix<BaseFloat> m = GetSubMatrix(submatrix_index);
498  KALDI_ASSERT(row >= 0 && row < m.NumRows() && num_cols == m.NumCols());
499  }
500  }
501 #endif
502  pointers->CopyFromVec(vec);
503 }
504 
505 void NnetComputer::GetPointers(int32 indexes_multi_index,
506  int32 num_cols,
507  CuArray<const BaseFloat*> *pointers) {
508  GetPointers(indexes_multi_index, num_cols,
509  reinterpret_cast<CuArray<BaseFloat*>*>(pointers));
510 }
511 
513  NVTX_RANGE(__func__);
514  const std::vector<NnetComputation::Command> &c = computation_.commands;
515  int32 num_commands = c.size();
516 
517  if (program_counter_ >= num_commands) {
518  computation_.Print(std::cerr, nnet_);
519  KALDI_ERR << "Running computation that has finished: program-counter="
520  << program_counter_;
521  }
523 
524  CommandDebugInfo info;
525  Timer timer;
526  double total_elapsed_previous = 0.0;
527 
528  for (; program_counter_ < num_commands; program_counter_++) {
529  if (c[program_counter_].command_type == kAcceptInput ||
530  c[program_counter_].command_type == kProvideOutput) {
531  // We have hit a part of the computation that requires user
532  // interaction, e.g. the end of the forward or backward phase.
533  break;
534  }
535  if (debug_)
537  ExecuteCommand();
538  if (debug_) {
539  double total_elapsed_now = timer.Elapsed();
541  total_elapsed_now - total_elapsed_previous);
542  total_elapsed_previous = total_elapsed_now;
543  }
544  }
545 }
546 
547 void NnetComputer::AcceptInput(const std::string &node_name,
548  CuMatrix<BaseFloat> *input) {
549  bool is_output = false;
550  int32 matrix_index = GetIoMatrixIndex(node_name, is_output);
551 
552  const NnetComputation::MatrixInfo &matrix_info =
553  computation_.matrices[matrix_index];
554  if (input->NumRows() != matrix_info.num_rows) {
555  KALDI_ERR << "Num-rows mismatch for input '" << node_name
556  << "': " << matrix_info.num_rows
557  << " in computation-request, " << input->NumRows()
558  << " provided.";
559  }
560  if (input->NumCols() != matrix_info.num_cols) {
561  KALDI_ERR << "Num-cols mismatch for input '" << node_name
562  << "': " << matrix_info.num_cols
563  << " in computation-request, " << input->NumCols()
564  << " provided.";
565  }
566  if (matrix_info.stride_type == kDefaultStride ||
567  input->Stride() == input->NumCols()) {
568  matrices_[matrix_index].Swap(input);
569  } else {
570  matrices_[matrix_index].Resize(matrix_info.num_rows,
571  matrix_info.num_cols,
573  matrices_[matrix_index].CopyFromMat(*input);
574  input->Resize(0, 0);
575  }
576 }
577 
579  const std::string &node_name) {
580  bool is_output = true;
581  int32 matrix_index = GetIoMatrixIndex(node_name, is_output);
582  KALDI_ASSERT(matrices_[matrix_index].NumRows() != 0);
583  return matrices_[matrix_index];
584 }
585 
586 
587 void NnetComputer::GetOutputDestructive(const std::string &node_name,
588  CuMatrix<BaseFloat> *output) {
589  bool is_output = true;
590  int32 matrix_index = GetIoMatrixIndex(node_name, is_output);
591  KALDI_ASSERT(matrices_[matrix_index].NumRows() != 0);
592  matrices_[matrix_index].Swap(output);
593  matrices_[matrix_index].Resize(0, 0);
594 }
595 
596 
598  const std::vector<NnetComputation::Command> &c = computation_.commands;
599  while (program_counter_ < static_cast<int32>(c.size()) &&
600  (c[program_counter_].command_type == kAcceptInput ||
601  c[program_counter_].command_type == kProvideOutput)) {
604  }
605  for (size_t i = 0; i < pending_commands_.size(); i++) {
606  // the order here doesn't really matter; we go from back to front
607  // as it's more efficient, not that efficiency really matters here.
608  int32 command = pending_commands_[i];
609  if (c[command].command_type == kAcceptInput) {
610  // we can't ignore if we needed input from the user that hasn't been
611  // provided.
612  int32 node = c[command].arg2;
613  KALDI_ERR << "Cannot run computation-- we did not get input for node '"
614  << nnet_.GetNodeName(node) << "'";
615  }
616  }
617  pending_commands_.clear();
618 }
619 
620 int32 NnetComputer::GetIoMatrixIndex(const std::string &node_name, bool is_output) {
621  const std::vector<NnetComputation::Command> &c = computation_.commands;
622  int32 node_index = nnet_.GetNodeIndex(node_name);
623  if (node_index == -1)
624  KALDI_ERR << "No node named '" << node_name << "'in network.";
625  // first make sure all the I/O commands that we immediately expect, are listed
626  // in 'pending_commands_'.
627  while (program_counter_ < static_cast<int32>(computation_.commands.size()) &&
628  ((c[program_counter_].command_type == kAcceptInput ||
629  c[program_counter_].command_type == kProvideOutput ||
630  c[program_counter_].command_type == kNoOperationMarker))) {
631  if (c[program_counter_].command_type != kNoOperationMarker)
634  }
635  for (size_t i = 0; i < pending_commands_.size(); i++) {
636  int32 command = pending_commands_[i];
637  bool this_command_is_output =
638  (c[command].command_type == kProvideOutput);
639  int32 this_submatrix_index = c[command].arg1,
640  this_node_index = c[command].arg2;
641  if (this_command_is_output == is_output && node_index == this_node_index) {
642  if (!is_output) {
643  pending_commands_.erase(pending_commands_.begin() + i);
644  // don't erase the command for outputs, as that would prevent things
645  // from being output twice, which is an unnecessary restriction.
646  }
647  if (!(computation_.IsWholeMatrix(this_submatrix_index)))
648  KALDI_ERR << "Getting input or output that is not a whole matrix "
649  << "(probably some optimization code needs to be changed)";
650  return computation_.submatrices[this_submatrix_index].matrix_index;
651  }
652  }
653  // if you get the following error it will likely be a bug in the calling code,
654  // or possibly due to giving the wrong egs.
655  KALDI_ERR << "Could not "
656  << (is_output ? "provide output " : "accept input ")
657  << "for network node " << node_name
658  << " (it is not expected at this point in the computation)";
659  return 0; // Suppress compiler warnings; this line will never be reached.
660 }
661 
662 
664  const std::vector<NnetIo> &io_vec) {
665  for (size_t i = 0; i < io_vec.size(); i++) {
666  const NnetIo &io = io_vec[i];
667  int32 node_index = nnet.GetNodeIndex(io.name);
668  if (node_index == -1)
669  KALDI_ERR << "No node named '" << io.name << "' in nnet.";
670  if (nnet.IsInputNode(node_index)) {
671  CuMatrix<BaseFloat> cu_input(io.features.NumRows(),
672  io.features.NumCols(),
673  kUndefined);
674  cu_input.CopyFromGeneralMat(io.features);
675  this->AcceptInput(io.name, &cu_input);
676  }
677  }
678 }
679 
681  // Delete any pointers that are present in compressed_matrices_. Actually
682  // they should all already have been deallocated and set to NULL if the
683  // compuation was run to completion; we do this in case someone ran
684  // the forward propagation but not the backprop.
685  for (size_t i = 0; i < compressed_matrices_.size(); i++)
686  delete compressed_matrices_[i];
687 }
688 
689 } // namespace nnet3
690 } // namespace kaldi
void GetPointers(int32 indexes_multi_index, int32 num_cols, CuArray< BaseFloat *> *pointers)
void Init(const NnetComputation &computation)
void CopyFromMat(const MatrixBase< OtherReal > &src, MatrixTransposeType trans=kNoTrans)
Definition: cu-matrix.cc:344
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
MatrixIndexT Stride() const
Definition: cu-matrix.h:217
virtual void * Propagate(const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in, CuMatrixBase< BaseFloat > *out) const =0
Propagate function.
void CopyFromVec(const std::vector< T > &src)
This function resizes if needed.
Definition: cu-array-inl.h:120
std::vector< BaseFloat > matrices_written_stddevs
Definition: nnet-compute.h:209
const std::string & GetNodeName(int32 node_index) const
returns individual node name.
Definition: nnet-nnet.cc:684
Abstract base-class for neural-net components.
void AddRows(Real alpha, const CuMatrixBase< Real > &src, const CuArrayBase< MatrixIndexT > &indexes)
Does for each row r, this.Row(r) += alpha * src.row(indexes[r]).
Definition: cu-matrix.cc:2766
void AddRowRanges(const CuMatrixBase< Real > &src, const CuArrayBase< Int32Pair > &indexes)
For each row r of this and for each column c, do (*this)(r, c) += src(j, c), where j ranges from ind...
Definition: cu-matrix.cc:2931
int32 GetVerboseLevel()
Get verbosity level, usually set via command line &#39;–verbose=&#39; switch.
Definition: kaldi-error.h:60
const NnetComputeOptions & options_
Definition: nnet-compute.h:132
virtual int32 NumParameters() const
The following new virtual function returns the total dimension of the parameters in this class...
void Print(std::ostream &os, const Nnet &nnet) const
std::vector< CommandAttributes > command_attributes_
Definition: nnet-compute.h:153
void * GetMemo(int32 memo_index)
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
kaldi::int32 int32
GeneralMatrix features
The features or labels.
Definition: nnet-example.h:46
void AddMat(Real alpha, const CuMatrixBase< Real > &A, MatrixTransposeType trans=kNoTrans)
*this += alpha * A
Definition: cu-matrix.cc:954
std::vector< MatrixInfo > matrices
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
NnetComputer(const NnetComputeOptions &options, const NnetComputation &computation, const Nnet &nnet, Nnet *nnet_to_update)
Constructor.
Definition: nnet-compute.cc:28
virtual void DeleteMemo(void *memo) const
This virtual function only needs to be overwritten by Components that return a non-NULL memo from the...
void ComputeCommandAttributes(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &vars, std::vector< CommandAttributes > *attributes)
std::vector< Command > commands
std::vector< BaseFloat > submatrices_written_stddevs
Definition: nnet-compute.h:213
virtual void Backprop(const std::string &debug_info, const ComponentPrecomputedIndexes *indexes, const CuMatrixBase< BaseFloat > &in_value, const CuMatrixBase< BaseFloat > &out_value, const CuMatrixBase< BaseFloat > &out_deriv, void *memo, Component *to_update, CuMatrixBase< BaseFloat > *in_deriv) const =0
Backprop function; depending on which of the arguments &#39;to_update&#39; and &#39;in_deriv&#39; are non-NULL...
void Scale(Real value)
Definition: cu-matrix.cc:644
void AcceptInput(const std::string &node_name, CuMatrix< BaseFloat > *input)
e.g.
MatrixIndexT NumCols() const
std::vector< int32 > pending_commands_
Definition: nnet-compute.h:141
std::vector< CuCompressedMatrixBase * > compressed_matrices_
Definition: nnet-compute.h:173
void GetCommandStrings(const Nnet &nnet, std::string *preamble, std::vector< std::string > *command_strings) const
std::vector< CuArray< int32 > > indexes_cuda
This class relates the matrices and sub-matrices in the computation to imaginary "variables", such that we can think of the operations as operating on sets of individual variables, and we can then do analysis that lets us do optimization.
Definition: nnet-analyze.h:121
const CuMatrixBase< BaseFloat > & GetOutput(const std::string &node_name)
void DebugBeforeExecute(int32 command, CommandDebugInfo *info)
Definition: nnet-compute.cc:82
std::vector< std::vector< std::pair< int32, int32 > > > indexes_multi
virtual void StoreStats(const CuMatrixBase< BaseFloat > &in_value, const CuMatrixBase< BaseFloat > &out_value, void *memo)
This function may store stats on average activation values, and for some component types...
virtual BaseFloat DotProduct(const UpdatableComponent &other) const =0
Computes dot-product between parameters of two instances of a Component.
virtual int32 Properties() const =0
Return bitmask of the component&#39;s properties.
void AddToRows(Real alpha, const CuArrayBase< MatrixIndexT > &indexes, CuMatrixBase< Real > *dst) const
For each row i of *this, adds this->Row(i) to dst->Row(indexes(i)) if indexes(i) >= 0...
Definition: cu-matrix.cc:2869
void SetZero()
Math operations, some calling kernels.
Definition: cu-matrix.cc:509
void AcceptInputs(const Nnet &nnet, const std::vector< NnetIo > &io)
This convenience function calls AcceptInput() in turn on all the inputs in the training example...
static BaseFloat ParameterStddev(const Component &c)
Definition: nnet-compute.cc:75
std::vector< SubMatrixInfo > submatrices
void CopyRows(const CuMatrixBase< Real > &src, const CuArrayBase< MatrixIndexT > &indexes)
Copies row r from row indexes[r] of src.
Definition: cu-matrix.cc:2678
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_PARANOID_ASSERT(cond)
Definition: kaldi-error.h:206
int32 GetIoMatrixIndex(const std::string &node_name, bool is_output)
#define KALDI_WARN
Definition: kaldi-error.h:150
Real TraceMatMat(const MatrixBase< Real > &A, const MatrixBase< Real > &B, MatrixTransposeType trans)
We need to declare this here as it will be a friend function.
std::vector< CuArray< Int32Pair > > indexes_ranges_cuda
const std::string & GetComponentName(int32 component_index) const
returns individual component name.
Definition: nnet-nnet.cc:689
This class is used for a piece of a CuMatrix.
Definition: matrix-common.h:70
const NnetComputation & computation_
Definition: nnet-compute.h:133
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
Class UpdatableComponent is a Component which has trainable parameters; it extends the interface of C...
std::vector< CuMatrix< BaseFloat > > matrices_
Definition: nnet-compute.h:160
void CopyFromGeneralMat(const GeneralMatrix &src, MatrixTransposeType trans=kNoTrans)
Definition: cu-matrix.cc:3096
std::vector< PrecomputedIndexesInfo > component_precomputed_indexes
const Real * Data() const
Return data pointer (const).
Definition: cu-matrix.h:746
void SaveMemo(int32 memo_index, const Component &c, void *memo)
Matrix for CUDA computing.
Definition: matrix-common.h:69
MatrixIndexT NumCols() const
Definition: cu-matrix.h:216
std::vector< std::string > submatrix_strings_
Definition: nnet-compute.h:155
class NnetComputer is responsible for executing the computation described in the "computation" object...
Definition: nnet-compute.h:59
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
#define NVTX_RANGE(name)
Definition: cu-common.h:143
std::string name
the name of the input in the neural net; in simple setups it will just be "input".
Definition: nnet-example.h:36
std::vector< std::string > command_strings_
Definition: nnet-compute.h:157
static BaseFloat MatrixStddev(const CuMatrixBase< BaseFloat > &m)
Definition: nnet-compute.cc:68
std::vector< std::vector< int32 > > indexes
void CopyToRows(const CuArrayBase< Real *> &dst) const
For each row r of this matrix, copies it to the array of floats at the location given by dst[r]...
Definition: cu-matrix.cc:2744
void GetOutputDestructive(const std::string &output_name, CuMatrix< BaseFloat > *output)
int32 GetNodeIndex(const std::string &node_name) const
returns index associated with this node name, or -1 if no such index.
Definition: nnet-nnet.cc:466
MatrixIndexT NumRows() const
Dimensions.
Definition: cu-matrix.h:215
Class CuCompressedMatrixBase is an abstract base class that allows you to compress a matrix of type C...
#define KALDI_LOG
Definition: kaldi-error.h:153
double Elapsed() const
Returns time in seconds.
Definition: timer.h:74
CuSubMatrix< BaseFloat > GetSubMatrix(int32 submatrix_index)
void Set(Real value)
Definition: cu-matrix.cc:531
virtual int32 NumRows() const =0
bool IsWholeMatrix(int32 submatrix_index) const
CuCompressedMatrixBase * NewCuCompressedMatrix(CuCompressedMatrixType t, BaseFloat range, bool truncat)
This function allocates a new CuCompressedMatrix with type determined by t, and with the &#39;range&#39; and ...
void Resize(MatrixIndexT rows, MatrixIndexT cols, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Allocate the memory.
Definition: cu-matrix.cc:50
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
std::vector< void * > memos_
Definition: nnet-compute.h:165
virtual int32 NumCols() const =0
virtual void CopyToMat(CuMatrixBase< BaseFloat > *mat) const =0
Copies the contents of *this to &#39;mat&#39;, which should be correctly sized beforehand.
void GetSubmatrixStrings(const Nnet &nnet, std::vector< std::string > *submat_strings) const
void DebugAfterExecute(int32 command, const CommandDebugInfo &info, double command_execution_time)
void Run()
This does either the forward or backward computation, depending when it is called (in a typical compu...
std::vector< std::vector< std::pair< int32, int32 > > > indexes_ranges