nnet-computation.cc
Go to the documentation of this file.
1 // nnet3/nnet-computation.cc
2 
3 // Copyright 2015-2017 Johns Hopkins University (author: Daniel Povey)
4 // 2015 Xiaohui Zhang
5 
6 // See ../../COPYING for clarification regarding multiple authors
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 // MERCHANTABLITY OR NON-INFRINGEMENT.
18 // See the Apache 2 License for the specific language governing permissions and
19 // limitations under the License.
20 
21 #include <iterator>
22 #include <sstream>
23 #include "nnet3/nnet-computation.h"
24 
25 namespace kaldi {
26 namespace nnet3 {
27 
28 
30  bool ans = false;
32  ans = true;
33  for (size_t i = 0; i < inputs.size(); i++) {
34  if (inputs[i].has_deriv) { // derivative requested for this input
35  ans = true;
36  break;
37  }
38  }
39  if (ans) {
40  // check that the output actually provides a derivative, else the
41  // request could not be meaningfully satisfied.
42  size_t i;
43  for (i = 0; i < outputs.size(); i++)
44  if (outputs[i].has_deriv)
45  break;
46  if (i == outputs.size()) {
47  KALDI_ERR << "You requested model derivatives or input derivatives, but "
48  << "provide no derivatives at the output.";
49  }
50  }
51  return ans;
52 }
53 
55  const std::string &node_name) const {
56  int32 ans = -1;
57  for (size_t i = 0; i < inputs.size(); i++) {
58  if (inputs[i].name == node_name) {
59  KALDI_ASSERT(ans == -1 && "Two inputs with the same name");
60  ans = i;
61  }
62  }
63  return ans;
64 }
65 
67  const std::string &node_name) const {
68  int32 ans = -1;
69  for (size_t i = 0; i < outputs.size(); i++) {
70  if (outputs[i].name == node_name) {
71  KALDI_ASSERT(ans == -1 && "Two inputs with the same name");
72  ans = i;
73  }
74  }
75  return ans;
76 }
77 
79  // note: component_precomputed_indexes[0].data is the NULL pointer.
80  for (size_t i = 1; i < component_precomputed_indexes.size(); i++)
81  delete component_precomputed_indexes[i].data;
82 }
83 
85  indexes_cuda.resize(indexes.size());
86 
87  for (size_t i = 0; i < indexes.size(); i++)
88  indexes_cuda[i].CopyFromVec(indexes[i]);
89 
90  KALDI_ASSERT(sizeof(Int32Pair) == sizeof(std::pair<int32,int32>));
91  indexes_ranges_cuda.resize(indexes_ranges.size());
92  for (int32 i = 0; i < indexes_ranges.size(); i++) {
93  const std::vector<std::pair<int32,int32> > *input = &(indexes_ranges[i]);
94  const std::vector<Int32Pair> *input_cast =
95  reinterpret_cast<const std::vector<Int32Pair> *>(input);
96  // note: the indexes for CUDA use can't very easily use STL types due to
97  // the interface of CUDA being plain C.
98  indexes_ranges_cuda[i].CopyFromVec(*input_cast);
99  }
100 }
101 
103  int32 row_offset, int32 num_rows,
104  int32 col_offset, int32 num_cols) {
105  KALDI_ASSERT(base_submatrix > 0 &&
106  static_cast<size_t>(base_submatrix) < submatrices.size());
107  const SubMatrixInfo &base_info = submatrices[base_submatrix];
108  int32 base_matrix = base_info.matrix_index;
109  KALDI_ASSERT(base_matrix > 0 &&
110  static_cast<size_t>(base_matrix) < matrices.size());
111  if (num_rows == -1) // we interpret this to mean 'as many as possible'.
112  num_rows = base_info.num_rows - row_offset;
113  if (num_cols == -1) // we interpret this to mean 'as many as possible'.
114  num_cols = base_info.num_cols - col_offset;
115  KALDI_ASSERT(row_offset + num_rows <= base_info.num_rows &&
116  col_offset + num_cols <= base_info.num_cols &&
117  row_offset >= 0 && col_offset >= 0 &&
118  num_rows > 0 && num_cols > 0);
119  int32 matrix_row_offset = base_info.row_offset + row_offset,
120  matrix_col_offset = base_info.col_offset + col_offset;
121  int32 ans = submatrices.size();
122  submatrices.push_back(
123  NnetComputation::SubMatrixInfo(base_matrix, matrix_row_offset, num_rows,
124  matrix_col_offset, num_cols));
125  return ans;
126 }
127 
129  MatrixStrideType stride_type) {
130  KALDI_ASSERT(num_rows > 0 && num_cols > 0);
131  if (matrices.empty()) { // Set up the zero matrix; index zero is reserved.
132  matrices.push_back(MatrixInfo(0, 0, kDefaultStride));
133  submatrices.push_back(SubMatrixInfo(0, 0, 0, 0, 0));
134  }
135  int32 matrix_index = matrices.size(),
136  submatrix_index = submatrices.size();
137  matrices.push_back(MatrixInfo(num_rows, num_cols, stride_type));
138  if (!matrix_debug_info.empty())
139  matrix_debug_info.push_back(MatrixDebugInfo());
140  submatrices.push_back(SubMatrixInfo(matrix_index, 0, num_rows, 0, num_cols));
141  return submatrix_index;
142 }
143 
144 void NnetComputation::MatrixInfo::Read(std::istream &is, bool binary) {
145  ExpectToken(is, binary, "<MatrixInfo>");
146  ExpectToken(is, binary, "<NumRows>");
147  ReadBasicType(is, binary, &num_rows);
148  ExpectToken(is, binary, "<NumCols>");
149  ReadBasicType(is, binary, &num_cols);
150  std::string tok;
151  ReadToken(is, binary, &tok);
152  if (tok == "</MatrixInfo>") {
153  stride_type = kDefaultStride;
154  } else {
155  KALDI_ASSERT(tok == "<StrideEqualNumCols>");
156  stride_type = kStrideEqualNumCols;
157  ExpectToken(is, binary, "</MatrixInfo>");
158  }
159 }
160 
161 void NnetComputation::MatrixInfo::Write(std::ostream &os, bool binary) const {
162  WriteToken(os, binary, "<MatrixInfo>");
163  if (!binary) os << std::endl;
164  WriteToken(os, binary, "<NumRows>");
165  WriteBasicType(os, binary, num_rows);
166  WriteToken(os, binary, "<NumCols>");
167  WriteBasicType(os, binary, num_cols);
168  if (stride_type != kDefaultStride)
169  WriteToken(os, binary, "<StrideEqualNumCols>");
170  if (!binary) os << std::endl;
171  WriteToken(os, binary, "</MatrixInfo>");
172  if (!binary) os << std::endl;
173 }
174 
177  std::swap(is_deriv, other->is_deriv);
178  cindexes.swap(other->cindexes);
179 }
180 
181 void NnetComputation::MatrixDebugInfo::Read(std::istream &is, bool binary) {
182  ExpectToken(is, binary, "<MatrixDebugInfo>");
183  ExpectToken(is, binary, "<IsDeriv>");
184  ReadBasicType(is, binary, &is_deriv);
185  ExpectToken(is, binary, "<Cindexes>");
186  ReadCindexVector(is, binary, &cindexes);
187  ExpectToken(is, binary, "</MatrixDebugInfo>");
188 }
189 
190 void NnetComputation::MatrixDebugInfo::Write(std::ostream &os, bool binary) const {
191  WriteToken(os, binary, "<MatrixDebugInfo>");
192  if (!binary) os << std::endl;
193  WriteToken(os, binary, "<IsDeriv>");
194  WriteBasicType(os, binary, is_deriv);
195  if (!binary) os << std::endl;
196  WriteToken(os, binary, "<Cindexes>");
197  WriteCindexVector(os, binary, cindexes);
198  if (!binary) os << std::endl;
199  WriteToken(os, binary, "</MatrixDebugInfo>");
200  if (!binary) os << std::endl;
201 }
202 
203 void NnetComputation::SubMatrixInfo::Read(std::istream &is, bool binary) {
204  ExpectToken(is, binary, "<SubMatrixInfo>");
205  ExpectToken(is, binary, "<MatrixIndex>");
206  ReadBasicType(is, binary, &matrix_index);
207  ExpectToken(is, binary, "<RowOffset>");
208  ReadBasicType(is, binary, &row_offset);
209  ExpectToken(is, binary, "<NumRows>");
210  ReadBasicType(is, binary, &num_rows);
211  ExpectToken(is, binary, "<ColOffset>");
212  ReadBasicType(is, binary, &col_offset);
213  ExpectToken(is, binary, "<NumCols>");
214  ReadBasicType(is, binary, &num_cols);
215  ExpectToken(is, binary, "</SubMatrixInfo>");
216 }
217 
218 void NnetComputation::SubMatrixInfo::Write(std::ostream &os, bool binary) const {
219  WriteToken(os, binary, "<SubMatrixInfo>");
220  if (!binary) os << std::endl;
221  WriteToken(os, binary, "<MatrixIndex>");
222  WriteBasicType(os, binary, matrix_index);
223  WriteToken(os, binary, "<RowOffset>");
224  WriteBasicType(os, binary, row_offset);
225  WriteToken(os, binary, "<NumRows>");
226  WriteBasicType(os, binary, num_rows);
227  WriteToken(os, binary, "<ColOffset>");
228  WriteBasicType(os, binary, col_offset);
229  WriteToken(os, binary, "<NumCols>");
230  WriteBasicType(os, binary, num_cols);
231  if (!binary) os << std::endl;
232  WriteToken(os, binary, "</SubMatrixInfo>");
233  if (!binary) os << std::endl;
234 }
235 
236 void NnetComputation::Command::Read(std::istream &is, bool binary) {
237  ExpectToken(is, binary, "<Cmd>");
238  if (binary) {
239  int32 command_type_int;
240  ReadBasicType(is, binary, &command_type_int);
241  command_type = static_cast<CommandType>(command_type_int);
242  ReadBasicType(is, binary, &alpha);
243  std::vector<int32> args;
244  ReadIntegerVector(is, binary, &args);
245  args.resize(7, -1); // extend with -1's.
246  int32 *dest = &arg1;
247  std::copy(args.begin(), args.end(), dest);
248  } else {
249  // this branch is slow but we don't care much, as we'd normally write in
250  // binary format.
251  std::string command_type_str;
252  getline(is, command_type_str);
253  if (command_type_str == "kAllocMatrix") {
254  command_type = kAllocMatrix;
255  } else if (command_type_str == "kDeallocMatrix") {
256  command_type = kDeallocMatrix;
257  } else if (command_type_str == "kSwapMatrix") {
258  command_type = kSwapMatrix;
259  } else if (command_type_str == "kSetConst") {
260  command_type = kSetConst;
261  } else if (command_type_str == "kPropagate") {
262  command_type = kPropagate;
263  } else if (command_type_str == "kBackprop") {
264  command_type = kBackprop;
265  } else if (command_type_str == "kBackpropNoModelUpdate") {
266  command_type = kBackpropNoModelUpdate;
267  } else if (command_type_str == "kMatrixCopy") {
268  command_type = kMatrixCopy;
269  } else if (command_type_str == "kMatrixAdd") {
270  command_type = kMatrixAdd;
271  } else if (command_type_str == "kCopyRows") {
272  command_type = kCopyRows;
273  } else if (command_type_str == "kAddRows") {
274  command_type = kAddRows;
275  } else if (command_type_str == "kCopyRowsMulti") {
276  command_type = kCopyRowsMulti;
277  } else if (command_type_str == "kCopyToRowsMulti") {
278  command_type = kCopyToRowsMulti;
279  } else if (command_type_str == "kAddRowsMulti") {
280  command_type = kAddRowsMulti;
281  } else if (command_type_str == "kAddToRowsMulti") {
282  command_type = kAddToRowsMulti;
283  } else if (command_type_str == "kAddRowRanges") {
284  command_type = kAddRowRanges;
285  } else if (command_type_str == "kCompressMatrix") {
286  command_type = kCompressMatrix;
287  } else if (command_type_str == "kDecompressMatrix") {
288  command_type = kDecompressMatrix;
289  } else if (command_type_str == "kAcceptInput") {
290  command_type = kAcceptInput;
291  } else if (command_type_str == "kProvideOutput") {
292  command_type = kProvideOutput;
293  } else if (command_type_str == "kNoOperation") {
294  command_type = kNoOperation;
295  } else if (command_type_str == "kNoOperationPermanent") {
296  command_type = kNoOperationPermanent;
297  } else if (command_type_str == "kNoOperationMarker") {
298  command_type = kNoOperationMarker;
299  } else if (command_type_str == "kNoOperationLabel") {
300  command_type = kNoOperationLabel;
301  } else if (command_type_str == "kGotoLabel") {
302  command_type = kGotoLabel;
303  } else {
304  KALDI_ERR << "Un-handled command type.";
305  }
306  ExpectToken(is, binary, "<Alpha>");
307  ReadBasicType(is, binary, &alpha);
308  ExpectToken(is, binary, "<Args>");
309  ReadBasicType(is, binary, &arg1);
310  ReadBasicType(is, binary, &arg2);
311  ReadBasicType(is, binary, &arg3);
312  ReadBasicType(is, binary, &arg4);
313  ReadBasicType(is, binary, &arg5);
314  ReadBasicType(is, binary, &arg6);
315  ReadBasicType(is, binary, &arg7);
316  }
317  ExpectToken(is, binary, "</Cmd>");
318 }
319 
320 void NnetComputation::Command::Write(std::ostream &os, bool binary) const {
321  WriteToken(os, binary, "<Cmd>");
322  if (binary) {
323  WriteBasicType(os, binary, static_cast<int32>(command_type));
324  WriteBasicType(os, binary, alpha);
325  std::vector<int32> args;
326  const int32 *src = &arg1;
327  args.insert(args.end(), src, src + 7); // arg1 through arg7.
328  while (!args.empty() && args.back() == -1)
329  args.pop_back();
330  WriteIntegerVector(os, binary, args);
331  } else {
332  std::string command_type_str;
333  switch (command_type) {
334  case kAllocMatrix:
335  os << "kAllocMatrix\n";
336  break;
337  case kDeallocMatrix:
338  os << "kDeallocMatrix\n";
339  break;
340  case kSwapMatrix:
341  os << "kSwapMatrix\n";
342  break;
343  case kSetConst:
344  os << "kSetConst\n";
345  break;
346  case kPropagate:
347  os << "kPropagate\n";
348  break;
349  case kBackprop:
350  os << "kBackprop\n";
351  break;
353  os << "kBackpropNoModelUpdate\n";
354  break;
355  case kMatrixCopy:
356  os << "kMatrixCopy\n";
357  break;
358  case kMatrixAdd:
359  os << "kMatrixAdd\n";
360  break;
361  case kCopyRows:
362  os << "kCopyRows\n";
363  break;
364  case kAddRows:
365  os << "kAddRows\n";
366  break;
367  case kCopyRowsMulti:
368  os << "kCopyRowsMulti\n";
369  break;
370  case kCopyToRowsMulti:
371  os << "kCopyToRowsMulti\n";
372  break;
373  case kAddRowsMulti:
374  os << "kAddRowsMulti\n";
375  break;
376  case kAddToRowsMulti:
377  os << "kAddToRowsMulti\n";
378  break;
379  case kAddRowRanges:
380  os << "kAddRowRanges\n";
381  break;
382  case kCompressMatrix:
383  os << "kCompressMatrix\n";
384  break;
385  case kDecompressMatrix:
386  os << "kDecompressMatrix\n";
387  break;
388  case kAcceptInput:
389  os << "kAcceptInput\n";
390  break;
391  case kProvideOutput:
392  os << "kProvideOutput\n";
393  break;
394  case kNoOperation:
395  os << "kNoOperation\n";
396  break;
398  os << "kNoOperationPermanent\n";
399  break;
400  case kNoOperationMarker:
401  os << "kNoOperationMarker\n";
402  break;
403  case kNoOperationLabel:
404  os << "kNoOperationLabel\n";
405  break;
406  case kGotoLabel:
407  os << "kGotoLabel\n";
408  break;
409  default:
410  KALDI_ERR << "Un-handled command type.";
411  }
412  os << "<Alpha> " << alpha << " ";
413  os << "<Args> " << arg1 << ' ' << arg2 << ' '
414  << arg3 << ' ' << arg4 << ' ' << arg5 << ' '
415  << arg6 << ' ' << arg7 << ' ';
416  }
417  WriteToken(os, binary, "</Cmd>");
418 }
419 
420 
421 // outputs a string explaining the meaning each sub-matrix in vaguely
422 // matlab-like notation: for whole matrices, something like "m1", "m2";
423 // and for parts of matrices, "m1(0:10, 20:40)".
425  const Nnet &nnet, std::vector<std::string> *submat_strings) const {
426  int32 num_submatrices = this->submatrices.size();
427  KALDI_ASSERT(num_submatrices > 0);
428  submat_strings->resize(num_submatrices);
429  (*submat_strings)[0] = "[]"; // the empty matrix
430  for (int32 i = 1; i < num_submatrices; i++) {
431  const NnetComputation::SubMatrixInfo &submat = this->submatrices[i];
432  std::ostringstream os;
433  if (this->IsWholeMatrix(i)) {
434  os << 'm' << submat.matrix_index;
435  } else { // part of a range.
436  os << 'm' << submat.matrix_index << '(' << submat.row_offset << ':'
437  << (submat.row_offset + submat.num_rows - 1) << ", "
438  << submat.col_offset << ':' << (submat.col_offset + submat.num_cols - 1)
439  << ')';
440  }
441  (*submat_strings)[i] = os.str();
442  }
443 }
444 
445 // outputs a string containing a text form of each of the elements of the
446 // "indexes" vector: if indexes[i] is (1, 2, 3), then (*indexes_strings)[i]
447 // is "1,2,3".
448 static void GetIndexesStrings(const Nnet &nnet,
449  const NnetComputation &computation,
450  std::vector<std::string> *indexes_strings) {
451  int32 size = computation.indexes.size();
452  indexes_strings->resize(size);
453  for (int32 i = 0; i < size; i++) {
454  std::ostringstream os;
455  PrintIntegerVector(os, computation.indexes[i]);
456  (*indexes_strings)[i] = os.str();
457  }
458 }
459 
460 // outputs a string containing a text form of each of the elements of the
461 // "indexes_multi" vector.
463  const Nnet &nnet,
464  const NnetComputation &computation,
465  std::vector<std::string> *indexes_multi_strings) {
466  int32 indexes_multi_size = computation.indexes_multi.size();
467  indexes_multi_strings->resize(indexes_multi_size);
468 
469  for (int32 i = 0; i < indexes_multi_size; i++) {
470  std::ostringstream os;
471  os << "[";
472  const std::vector<std::pair<int32, int32> > &vec =
473  computation.indexes_multi[i];
474  int32 size = vec.size();
475  for (int32 j = 0; j < size; j++) {
476  int32 submat_index = vec[j].first, row_index = vec[j].second;
477  if (submat_index == -1) {
478  os << "NULL";
479  } else {
480  const NnetComputation::SubMatrixInfo &submat =
481  computation.submatrices[submat_index];
482  const NnetComputation::MatrixInfo &mat =
483  computation.matrices[submat.matrix_index];
484  int32 row = row_index + submat.row_offset;
485  int32 col_start = submat.col_offset,
486  col_end = col_start + submat.num_cols;
487  if (!(row_index < submat.num_rows &&
488  row < mat.num_rows)) {
489  KALDI_WARN << "Invalid indexes in indexes-multi[" << i
490  << ": submatrix " << submat_index << " = m"
491  << submat.matrix_index << "(" << submat.row_offset
492  << ':' << (submat.row_offset + submat.num_rows - 1)
493  << ',' << submat.col_offset << ':'
494  << (submat.col_offset + submat.num_cols - 1) << ") has "
495  << submat.num_rows << " rows, but you access row "
496  << row_index;
497  }
498  if (col_start == 0 && col_end == mat.num_cols)
499  os << 'm' << submat.matrix_index << '(' << row << ",:)";
500  else
501  os << 'm' << submat.matrix_index << '(' << row << ',' << col_start
502  << ':' << (col_end - 1) << ')';
503  }
504  if (j + 1 < size) os << ",";
505  }
506  os << "]";
507  (*indexes_multi_strings)[i] = os.str();
508  }
509 }
510 
511 
512 // writes to "os" the statement for this command.
513 static void PrintCommand(std::ostream &os_out,
514  const Nnet &nnet,
515  const NnetComputation &computation,
516  int32 command_index,
517  const std::vector<std::string> &submatrix_strings,
518  const std::vector<std::string> &indexes_strings,
519  const std::vector<std::string> &indexes_multi_strings) {
520  // If the string is longer than 'max_string_length' characters, it will
521  // be summarized with '...' in the middle.
522  size_t max_string_length = 200;
523  std::ostringstream os;
524  KALDI_ASSERT(command_index < computation.commands.size());
525  os << "c" << command_index << ": ";
526  const NnetComputation::Command &c = computation.commands[command_index];
527  switch (c.command_type) {
528  case kAllocMatrix:
529  os << submatrix_strings[c.arg1] << " = undefined("
530  << computation.submatrices[c.arg1].num_rows
531  << ',' << computation.submatrices[c.arg1].num_cols << ")\n";
532  break;
533  case kDeallocMatrix:
534  os << submatrix_strings[c.arg1] << " = []\n";
535  break;
536  case kSwapMatrix:
537  os << submatrix_strings[c.arg1] << ".swap("
538  << submatrix_strings[c.arg2] << ") [dim = "
539  << computation.submatrices[c.arg1].num_rows << " x "
540  << computation.submatrices[c.arg1].num_cols << "]\n";
541  break;
542  case kSetConst:
543  os << submatrix_strings[c.arg1] << ".set(" << c.alpha << ") [dim = "
544  << computation.submatrices[c.arg1].num_rows << " x "
545  << computation.submatrices[c.arg1].num_cols << "];\n";
546  break;
547  case kPropagate:
548  os << nnet.GetComponentName(c.arg1) << ".Propagate(";
549  if (c.arg2 == 0) os << "NULL, ";
550  else os << "precomputed_indexes[" << c.arg2 << "], ";
551  os << submatrix_strings[c.arg3] << ", &" << submatrix_strings[c.arg4]
552  << ")\n";
553  break;
554  case kBackprop:
555  case kBackpropNoModelUpdate: {
556  int32 component_index = c.arg1;
557  os << nnet.GetComponentName(component_index) << ".Backprop(";
558  if (c.arg2 == 0) os << "NULL, ";
559  else os << "precomputed_indexes[" << c.arg2 << "], ";
560  os << submatrix_strings[c.arg3] << ", "
561  << submatrix_strings[c.arg4] << ", "
562  << submatrix_strings[c.arg5] << ", "
563  << (computation.need_model_derivative &&
564  c.command_type == kBackprop ?
565  "[component-pointer], " : "NULL, ")
566  << (c.arg6 == 0 ? std::string("NULL") :
567  std::string("&") + submatrix_strings[c.arg6]) << ")\n";
568  break;
569  }
570  case kMatrixCopy:
571  if (c.alpha == 1.0) {
572  os << submatrix_strings[c.arg1] << " = "
573  << submatrix_strings[c.arg2] << "\n";
574  } else {
575  os << submatrix_strings[c.arg1] << " = "
576  << c.alpha << " * "
577  << submatrix_strings[c.arg2] << "\n";
578  }
579  break;
580  case kMatrixAdd:
581  if (c.alpha == 1.0) {
582  os << submatrix_strings[c.arg1] << " += "
583  << submatrix_strings[c.arg2] << "\n";
584  } else {
585  os << submatrix_strings[c.arg1] << " += "
586  << c.alpha << " * "
587  << submatrix_strings[c.arg2] << "\n";
588  }
589  break;
590  case kAddRows:
591  case kCopyRows:
592  os << submatrix_strings[c.arg1] << "."
593  << (c.command_type == kAddRows ? "AddRows" :
594  "CopyRows") << "(" << c.alpha << ", "
595  << submatrix_strings[c.arg2] << indexes_strings[c.arg3] << ")\n";
596  break;
597  case kAddRowsMulti:
598  case kAddToRowsMulti:
599  case kCopyRowsMulti:
600  case kCopyToRowsMulti: {
601  CommandType ct = c.command_type;
602  os << submatrix_strings[c.arg1] << "."
603  << (ct == kAddRowsMulti ? "AddRowsMulti" :
604  (ct == kAddToRowsMulti? "AddToRowsMulti" :
605  (ct == kCopyRowsMulti ? "CopyRowsMulti" :
606  "CopyToRowsMulti"))) << "("
607  << c.alpha << ", "
608  << indexes_multi_strings[c.arg2] << ")\n";
609  break;
610  }
611  case kAddRowRanges: {
612  os << submatrix_strings[c.arg1] << ".AddRowRanges("
613  << c.alpha << ", "
614  << submatrix_strings[c.arg2] << ", [";
615  const std::vector<std::pair<int32, int32> > &pairs =
616  computation.indexes_ranges[c.arg3];
617  for (size_t i = 0; i < pairs.size(); i++) {
618  if (pairs[i].first == -1) {
619  os << "null";
620  } else {
621  os << pairs[i].first << ":" << (pairs[i].second - 1);
622  }
623  if (i + 1 < pairs.size()) os << ",";
624  }
625  os << "])\n";
626  break;
627  }
628  case kCompressMatrix: {
629  BaseFloat range = c.alpha;
630  std::string truncate = (c.arg3 != 0 ? "true" : "false");
631  std::string compressed_matrix_type;
632  if (c.arg2 == kCompressedMatrixInt8) { compressed_matrix_type = "int8"; }
633  else if (c.arg2 == kCompressedMatrixUint8) { compressed_matrix_type = "uint8"; }
634  else if (c.arg2 == kCompressedMatrixInt16) { compressed_matrix_type = "int16"; }
635  else {
637  compressed_matrix_type = "uint16";
638  }
639  os << "CompressMatrix(" << submatrix_strings[c.arg1] << ", "
640  << range << ", " << compressed_matrix_type << ", "
641  << truncate << ")\n";
642  break;
643  }
644  case kDecompressMatrix:
645  os << "DecompressMatrix(" << submatrix_strings[c.arg1] << ")\n";
646  break;
647  case kAcceptInput:
648  os << submatrix_strings[c.arg1] << " = user input [for node: '"
649  << nnet.GetNodeName(c.arg2) << "']\n";
650  break;
651  case kProvideOutput:
652  os << "output " << submatrix_strings[c.arg1] << " to user"
653  << " [for node: '" << nnet.GetNodeName(c.arg2) << "']\n";
654  break;
655  case kNoOperation:
656  os << "[no-op]\n";
657  break;
659  os << "[no-op-permanent]\n";
660  break;
661  case kNoOperationMarker:
662  os << "# computation segment separator [e.g., begin backward commands]\n";
663  break;
664  case kNoOperationLabel:
665  os << "[label for goto statement]\n";
666  break;
667  case kGotoLabel:
668  os << "goto c" << c.arg1 << "\n";
669  break;
670  default:
671  KALDI_ERR << "Un-handled command type.";
672  }
673  std::string str = os.str();
674  if (str.size() <= max_string_length) {
675  os_out << str;
676  } else {
677  size_t len = str.size();
678  os_out << str.substr(0, max_string_length / 2) << " ... "
679  << str.substr(len - max_string_length / 2);
680  }
681 }
682 
683 
685  std::ostream &os,
686  const NnetComputation &c,
687  const Nnet &nnet,
688  const std::vector<std::string> &submatrix_strings,
689  const std::vector<std::string> &indexes_strings,
690  const std::vector<std::string> &indexes_multi_strings) {
691 
692  // First print info about the matrices.
693  os << "matrix ";
694  for (int32 i = 1; i < c.matrices.size(); i++) {
695  os << "m" << i << "(" << c.matrices[i].num_rows
696  << ", " << c.matrices[i].num_cols << ")";
697  if (i + 1 < c.matrices.size())
698  os << ", ";
699  }
700  os << "\n";
701  if (!c.matrix_debug_info.empty()) {
702  os << "# The following show how matrices correspond to network-nodes and\n"
703  << "# cindex-ids. Format is: matrix = <node-id>.[value|deriv][ <list-of-cindex-ids> ]\n"
704  << "# where a cindex-id is written as (n,t[,x]) but ranges of t values are compressed\n"
705  << "# so we write (n, tfirst:tlast).\n";
706  KALDI_ASSERT(c.matrix_debug_info.size() == c.matrices.size());
707  for (int32 i = 1; i < c.matrices.size(); i++) {
708  const NnetComputation::MatrixDebugInfo &debug_info =
709  c.matrix_debug_info[i];
710  os << "m" << i << " == " << (debug_info.is_deriv ? "deriv: " : "value: ");
711  PrintCindexes(os, debug_info.cindexes, nnet.GetNodeNames());
712  os << "\n";
713  }
714  }
715 }
716 
717 void NnetComputation::Print(std::ostream &os, const Nnet &nnet) const {
718  std::vector<std::string> submatrix_strings, indexes_strings,
719  indexes_multi_strings;
720  this->GetSubmatrixStrings(nnet, &submatrix_strings);
721  GetIndexesStrings(nnet, *this, &indexes_strings);
722  GetIndexesMultiStrings(nnet, *this, &indexes_multi_strings);
723  PrintComputationPreamble(os, *this, nnet, submatrix_strings,
724  indexes_strings, indexes_multi_strings);
725  os << "# begin forward commands\n";
726  for (int32 c = 0; c < commands.size(); c++) {
727  PrintCommand(os, nnet, *this, c, submatrix_strings,
728  indexes_strings, indexes_multi_strings);
729  }
730 }
731 
732 void NnetComputation::Read(std::istream &is, bool binary) {
733  int32 version = 5, // must be in sync with 'version' in Write.
734  version_in = 1; // defaults to 1 if no version specified.
735 
736  ExpectToken(is, binary, "<NnetComputation>");
737  std::string token;
738  ReadToken(is, binary, &token);
739  if (token == "<Version>") {
740  ReadBasicType(is, binary, &version_in);
741  ExpectToken(is, binary, "<NumMatrices>");
742  } else {
743  KALDI_ASSERT(token == "<NumMatrices>");
744  }
745  if (version_in != version) {
746  KALDI_ERR << "Reading NnetComputation failed because version in "
747  << version_in << " != " << version << "... you can "
748  << "ignore this error if the program continues afterward, "
749  << "it would only affect speed.";
750  }
751  size_t num_matrices;
752  ReadBasicType(is, binary, &num_matrices);
753  KALDI_ASSERT(num_matrices >= 0);
754  matrices.resize(num_matrices);
755  ExpectToken(is, binary, "<Matrices>");
756  for (size_t c = 0; c < num_matrices; c++) {
757  matrices[c].Read(is, binary);
758  }
759 
760  size_t num_matrix_debug_info;
761  ExpectToken(is, binary, "<NumMatrixDebugInfo>");
762  ReadBasicType(is, binary, &num_matrix_debug_info);
763  KALDI_ASSERT(num_matrix_debug_info >= 0);
764  matrix_debug_info.resize(num_matrix_debug_info);
765  ExpectToken(is, binary, "<MatrixDebugInfo>");
766  for (size_t c = 0; c < num_matrix_debug_info; c++) {
767  matrix_debug_info[c].Read(is, binary);
768  }
769 
770  size_t num_submatrices;
771  ExpectToken(is, binary, "<NumSubMatrices>");
772  ReadBasicType(is, binary, &num_submatrices);
773  KALDI_ASSERT(num_submatrices >= 0);
774  submatrices.resize(num_submatrices);
775  ExpectToken(is, binary, "<SubMatrices>");
776  for (size_t c = 0; c < num_submatrices; c++) {
777  submatrices[c].Read(is, binary);
778  }
779 
780 
781  // delete any existing pointers in component_precomputed_indexes.
782  // note: component_precomputed_indexes[0] is the NULL pointer.
783  for (size_t i = 1; i < component_precomputed_indexes.size(); i++)
784  delete component_precomputed_indexes[i].data;
785  component_precomputed_indexes.clear();
786 
787  size_t num_component_precomputed_indexes;
788  ExpectToken(is, binary, "<NumComponentPrecomputedIndexes>");
789  ReadBasicType(is, binary, &num_component_precomputed_indexes);
790  KALDI_ASSERT(num_component_precomputed_indexes >= 0);
791  component_precomputed_indexes.resize(num_component_precomputed_indexes);
792 
793  std::string tok;
794  ReadToken(is, binary, &tok);
795  if (tok == "<ComponentPrecomputedIndexes>") {
796  // Older on-disk format, before that code was extended for shortcut
797  // compilation.
798  component_precomputed_indexes.clear();
799  component_precomputed_indexes.resize(num_component_precomputed_indexes);
800  for (size_t c = 0; c < num_component_precomputed_indexes; c++) {
801  bool is_null; // a boolean indicating whether the pointer should be NULL.
802  ReadBasicType(is, binary, &is_null);
803  if (!is_null) {
805  component_precomputed_indexes[c].data = p;
806  }
807  }
808  } else {
809  KALDI_ASSERT(tok == "<PrecomputedIndexesInfo>");
810  for (size_t c = 1; c < num_component_precomputed_indexes; c++) {
812  KALDI_ASSERT(p != NULL);
813  PrecomputedIndexesInfo &info = component_precomputed_indexes[c];
814  info.data = p;
815  ReadIndexVector(is, binary, &(info.input_indexes));
816  ReadIndexVector(is, binary, &(info.output_indexes));
817  }
818  }
819  size_t num_indexes;
820  ExpectToken(is, binary, "<NumIndexes>");
821  ReadBasicType(is, binary, &num_indexes);
822  KALDI_ASSERT(num_indexes >= 0);
823  indexes.resize(num_indexes);
824  ExpectToken(is, binary, "<Indexes>");
825  for (size_t c = 0; c < num_indexes; c++) {
826  ReadIntegerVector(is, binary, &(indexes[c]));
827  }
828 
829  size_t num_indexes_multi;
830  ExpectToken(is, binary, "<NumIndexesMulti>");
831  ReadBasicType(is, binary, &num_indexes_multi);
832  KALDI_ASSERT(num_indexes_multi >= 0);
833  indexes_multi.resize(num_indexes_multi);
834  ExpectToken(is, binary, "<IndexesMulti>");
835  for (size_t c = 0; c < num_indexes_multi; c++) {
836  ReadIntegerPairVector(is, binary, &(indexes_multi[c]));
837  }
838 
839  size_t num_indexes_ranges;
840  ExpectToken(is, binary, "<NumIndexesRanges>");
841  ReadBasicType(is, binary, &num_indexes_ranges);
842  KALDI_ASSERT(num_indexes_ranges >= 0);
843  indexes_ranges.resize(num_indexes_ranges);
844  ExpectToken(is, binary, "<IndexesRanges>");
845  for (size_t c = 0; c < num_indexes_ranges; c++) {
846  ReadIntegerPairVector(is, binary, &(indexes_ranges[c]));
847  }
848 
849  size_t num_commands;
850  ExpectToken(is, binary, "<NumCommands>");
851  ReadBasicType(is, binary, &num_commands);
852  KALDI_ASSERT(num_commands >= 0);
853  commands.resize(num_commands);
854  ExpectToken(is, binary, "<Commands>");
855  for (size_t c = 0; c < num_commands; c++) {
856  commands[c].Read(is, binary);
857  }
858 
859  ExpectToken(is, binary, "<NeedModelDerivative>");
860  ReadBasicType(is, binary, &need_model_derivative);
861 
862  ComputeCudaIndexes();
863  ExpectToken(is, binary, "</NnetComputation>");
864 }
865 
866 void NnetComputation::Write(std::ostream &os, bool binary) const {
867  int32 version = 5; // Must be in sync with version in Read.
868  WriteToken(os, binary, "<NnetComputation>");
869  WriteToken(os, binary, "<Version>");
870  WriteBasicType(os, binary, version);
871  WriteToken(os, binary, "<NumMatrices>");
872  WriteBasicType(os, binary, matrices.size());
873  WriteToken(os, binary, "<Matrices>");
874  for (size_t c = 0; c < matrices.size(); c++) {
875  matrices[c].Write(os, binary);
876  }
877 
878  if (!binary) os << std::endl;
879  WriteToken(os, binary, "<NumMatrixDebugInfo>");
880  WriteBasicType(os, binary, matrix_debug_info.size());
881  WriteToken(os, binary, "<MatrixDebugInfo>");
882  for (size_t c = 0; c < matrix_debug_info.size(); c++) {
883  matrix_debug_info[c].Write(os, binary);
884  }
885 
886  if (!binary) os << std::endl;
887  WriteToken(os, binary, "<NumSubMatrices>");
888  WriteBasicType(os, binary, submatrices.size());
889  WriteToken(os, binary, "<SubMatrices>");
890  for (size_t c = 0; c < submatrices.size(); c++) {
891  submatrices[c].Write(os, binary);
892  }
893 
894  if (!binary) os << std::endl;
895  WriteToken(os, binary, "<NumComponentPrecomputedIndexes>");
896  WriteBasicType(os, binary, component_precomputed_indexes.size());
897  WriteToken(os, binary, "<PrecomputedIndexesInfo>");
898  for (size_t c = 1; c < component_precomputed_indexes.size(); c++) {
899  const PrecomputedIndexesInfo &info = component_precomputed_indexes[c];
900  info.data->Write(os, binary);
901  WriteIndexVector(os, binary, info.input_indexes);
902  WriteIndexVector(os, binary, info.output_indexes);
903  }
904 
905  if (!binary) os << std::endl;
906  WriteToken(os, binary, "<NumIndexes>");
907  WriteBasicType(os, binary, indexes.size());
908  WriteToken(os, binary, "<Indexes>");
909  for (size_t c = 0; c < indexes.size(); c++) {
910  WriteIntegerVector(os, binary, indexes[c]);
911  }
912 
913  if (!binary) os << std::endl;
914  WriteToken(os, binary, "<NumIndexesMulti>");
915  WriteBasicType(os, binary, indexes_multi.size());
916  WriteToken(os, binary, "<IndexesMulti>");
917  for (size_t c = 0; c < indexes_multi.size(); c++) {
918  WriteIntegerPairVector(os, binary, indexes_multi[c]);
919  }
920 
921  if (!binary) os << std::endl;
922  WriteToken(os, binary, "<NumIndexesRanges>");
923  WriteBasicType(os, binary, indexes_ranges.size());
924  WriteToken(os, binary, "<IndexesRanges>");
925  for (size_t c = 0; c < indexes_ranges.size(); c++) {
926  WriteIntegerPairVector(os, binary, indexes_ranges[c]);
927  }
928 
929  if (!binary) os << std::endl;
930  WriteToken(os, binary, "<NumCommands>");
931  WriteBasicType(os, binary, commands.size());
932  WriteToken(os, binary, "<Commands>");
933  for (size_t c = 0; c < commands.size(); c++) {
934  commands[c].Write(os, binary);
935  }
936 
937  if (!binary) os << std::endl;
938  WriteToken(os, binary, "<NeedModelDerivative>");
940  WriteToken(os, binary, "</NnetComputation>");
941  if (!binary) os << std::endl;
942 }
943 
945  const Nnet &nnet,
946  std::string *preamble,
947  std::vector<std::string> *command_strings) const {
948  std::vector<std::string> submatrix_strings, indexes_strings,
949  indexes_multi_strings;
950  this->GetSubmatrixStrings(nnet, &submatrix_strings);
951  GetIndexesStrings(nnet, *this, &indexes_strings);
952  GetIndexesMultiStrings(nnet, *this, &indexes_multi_strings);
953  if (preamble != NULL) {
954  std::ostringstream os;
955  PrintComputationPreamble(os, *this, nnet, submatrix_strings,
956  indexes_strings, indexes_multi_strings);
957  *preamble = os.str();
958  }
959  if (command_strings != NULL) {
960  command_strings->resize(commands.size());
961  for (int32 c = 0; c < commands.size(); c++) {
962  std::ostringstream os;
963  PrintCommand(os, nnet, *this, c, submatrix_strings,
964  indexes_strings, indexes_multi_strings);
965  (*command_strings)[c] = os.str();
966  // Remove the final newline.
967  std::string &str = (*command_strings)[c];
968  if (!str.empty())
969  str.resize(str.size() - 1);
970  }
971  }
972 }
973 
974 
975 bool NnetComputation::IsWholeMatrix(int32 submatrix_index) const {
976  KALDI_ASSERT(submatrix_index > 0 && submatrix_index < submatrices.size());
977  const SubMatrixInfo &submat_info = submatrices[submatrix_index];
978  const MatrixInfo &mat_info = matrices[submat_info.matrix_index];
979  return submat_info.row_offset == 0 && submat_info.col_offset == 0 &&
980  submat_info.num_rows == mat_info.num_rows &&
981  submat_info.num_cols == mat_info.num_cols;
982 }
983 
985  const NnetComputation::SubMatrixInfo &other) const {
986  return matrix_index == other.matrix_index &&
987  row_offset == other.row_offset &&
988  num_rows == other.num_rows &&
989  col_offset == other.col_offset &&
990  num_cols == other.num_cols;
991 }
992 
993 void IoSpecification::Print(std::ostream &os) const {
994  os << "name=" << name << ", has-deriv=" << (has_deriv ? "true" : "false" )
995  << ", indexes=";
996  PrintIndexes(os, indexes);
997  os << "\n";
998 }
999 
1001  name.swap(other->name);
1002  indexes.swap(other->indexes);
1003  std::swap(has_deriv, other->has_deriv);
1004 }
1005 
1006 void IoSpecification::Read(std::istream &is, bool binary) {
1007  ExpectToken(is, binary, "<IoSpecification>");
1008  ReadToken(is, binary, &name);
1009  ExpectToken(is, binary, "<NumIndexes>");
1010  size_t num_indexes;
1011  ReadBasicType(is, binary, &num_indexes);
1012  ExpectToken(is, binary, "<Indexes>");
1013  ReadIndexVector(is, binary, &indexes);
1014  ExpectToken(is, binary, "<HasDeriv>");
1015  ReadBasicType(is, binary, &has_deriv);
1016  ExpectToken(is, binary, "</IoSpecification>");
1017 }
1018 
1019 void IoSpecification::Write(std::ostream &os, bool binary) const {
1020  WriteToken(os, binary, "<IoSpecification>");
1021  if (!binary) os << std::endl;
1022  WriteToken(os, binary, name);
1023  WriteToken(os, binary, "<NumIndexes>");
1024  WriteBasicType(os, binary, indexes.size());
1025  WriteToken(os, binary, "<Indexes>");
1026  WriteIndexVector(os, binary, indexes);
1027  WriteToken(os, binary, "<HasDeriv>");
1028  WriteBasicType(os, binary, has_deriv);
1029  if (!binary) os << std::endl;
1030  WriteToken(os, binary, "</IoSpecification>");
1031  if (!binary) os << std::endl;
1032 }
1033 
1034 void ComputationRequest::Read(std::istream &is, bool binary) {
1035  ExpectToken(is, binary, "<ComputationRequest>");
1036  size_t num_inputs;
1037  ExpectToken(is, binary, "<NumInputs>");
1038  ReadBasicType(is, binary, &num_inputs);
1039  KALDI_ASSERT(num_inputs >= 0);
1040  inputs.resize(num_inputs);
1041  ExpectToken(is, binary, "<Inputs>");
1042  for (size_t c = 0; c < num_inputs; c++) {
1043  inputs[c].Read(is, binary);
1044  }
1045 
1046  size_t num_outputs;
1047  ExpectToken(is, binary, "<NumOutputs>");
1048  ReadBasicType(is, binary, &num_outputs);
1049  KALDI_ASSERT(num_outputs >= 0);
1050  outputs.resize(num_outputs);
1051  ExpectToken(is, binary, "<Outputs>");
1052  for (size_t c = 0; c < num_outputs; c++) {
1053  outputs[c].Read(is, binary);
1054  }
1055 
1056  ExpectToken(is, binary, "<NeedModelDerivative>");
1057  ReadBasicType(is, binary, &need_model_derivative);
1058  ExpectToken(is, binary, "<StoreComponentStats>");
1059  ReadBasicType(is, binary, &store_component_stats);
1060  ExpectToken(is, binary, "</ComputationRequest>");
1061 }
1062 
1063 void ComputationRequest::Write(std::ostream &os, bool binary) const {
1064  WriteToken(os, binary, "<ComputationRequest>");
1065  if (!binary) os << std::endl;
1066  WriteToken(os, binary, "<NumInputs>");
1067  WriteBasicType(os, binary, inputs.size());
1068  if (!binary) os << std::endl;
1069  WriteToken(os, binary, "<Inputs>");
1070  for (size_t c = 0; c < inputs.size(); c++) {
1071  inputs[c].Write(os, binary);
1072  }
1073  if (!binary) os << std::endl;
1074 
1075  WriteToken(os, binary, "<NumOutputs>");
1076  WriteBasicType(os, binary, outputs.size());
1077  if (!binary) os << std::endl;
1078  WriteToken(os, binary, "<Outputs>");
1079  for (size_t c = 0; c < outputs.size(); c++) {
1080  outputs[c].Write(os, binary);
1081  }
1082  if (!binary) os << std::endl;
1083 
1084  WriteToken(os, binary, "<NeedModelDerivative>");
1086  WriteToken(os, binary, "<StoreComponentStats>");
1088  WriteToken(os, binary, "</ComputationRequest>");
1089  if (!binary) os << std::endl;
1090 }
1091 
1092 void ComputationRequest::Print(std::ostream &os) const {
1093  os << " # Computation request:\n";
1094  for (size_t i = 0; i < inputs.size(); i++) {
1095  os << "input-" << i << ": ";
1096  inputs[i].Print(os);
1097  }
1098  for (size_t i = 0; i < outputs.size(); i++) {
1099  os << "output-" << i << ": ";
1100  outputs[i].Print(os);
1101  }
1102  os << "need-model-derivative: " <<
1103  (need_model_derivative ? "true\n" : "false\n");
1104  os << "store-component-stats: " <<
1105  (store_component_stats ? "true\n" : "false\n");
1106  misc_info.Print(os);
1107 }
1108 
1110  return (name == other.name && indexes == other.indexes &&
1111  has_deriv == other.has_deriv);
1112 }
1113 
1114 IoSpecification::IoSpecification(const std::string &name,
1115  int32 t_start, int32 t_end):
1116  name(name), indexes(std::max<int32>(0, t_end - t_start)),
1117  has_deriv(false) {
1118  // the n and x values will already be 0 in "indexes" because
1119  // the default constructor does that; so just set the t values.
1120  std::vector<Index>::iterator iter = indexes.begin(), end = indexes.end();
1121  for (int32 t = t_start; iter != end; ++iter, ++t)
1122  iter->t = t;
1123 }
1124 
1126  // rely on the std::vector's default implementation of ==, which in turn
1127  // relies on the == operator of class IoSpecification.
1128  return inputs == other.inputs && outputs == other.outputs &&
1131  misc_info == other.misc_info;
1132 }
1133 
1135  matrices(other.matrices),
1136  matrix_debug_info(other.matrix_debug_info),
1137  submatrices(other.submatrices),
1138  component_precomputed_indexes(other.component_precomputed_indexes),
1139  indexes(other.indexes),
1140  indexes_multi(other.indexes_multi),
1141  indexes_ranges(other.indexes_ranges),
1142  commands(other.commands),
1144  indexes_cuda(other.indexes_cuda),
1145  indexes_ranges_cuda(other.indexes_ranges_cuda) {
1146  for (size_t i = 1; i < component_precomputed_indexes.size(); i++)
1148  component_precomputed_indexes[i].data->Copy();
1149 }
1150 
1152  matrices = other.matrices;
1154  submatrices = other.submatrices;
1155  indexes = other.indexes;
1156  indexes_multi = other.indexes_multi;
1158  commands = other.commands;
1160  indexes_cuda = other.indexes_cuda;
1162 
1163  for (size_t i = 1; i < component_precomputed_indexes.size(); i++)
1164  delete component_precomputed_indexes[i].data;
1166  for (size_t i = 1; i < component_precomputed_indexes.size(); i++)
1168  component_precomputed_indexes[i].data->Copy();
1169  return *this;
1170 }
1171 
1172 
1174  std::vector<int32> *whole_submatrices) const {
1175  int32 num_matrices = matrices.size(),
1176  num_submatrices = submatrices.size();
1177  whole_submatrices->clear();
1178  whole_submatrices->resize(num_matrices, 0);
1179  for (int32 s = 1; s < num_submatrices; s++) {
1180  if (IsWholeMatrix(s)) {
1181  int32 m = submatrices[s].matrix_index;
1182  (*whole_submatrices)[m] = s;
1183  }
1184  }
1185  for (int32 m = 1; m < num_matrices; m++) {
1186  KALDI_ASSERT((*whole_submatrices)[m] != 0 &&
1187  "Matrix exists with no submatrix that is "
1188  "the whole of it.");
1189  }
1190 }
1191 
1193  const IoSpecification &io_spec) const noexcept {
1194  StringHasher string_hasher;
1195  IndexVectorHasher indexes_hasher;
1196  // 4261 was chosen at random from a list of primes.
1197  return string_hasher(io_spec.name) +
1198  indexes_hasher(io_spec.indexes) +
1199  (io_spec.has_deriv ? 4261 : 0);
1200 }
1201 
1202 // ComputationRequests are distinguished by the names and indexes
1203 // of inputs and outputs
1205  const ComputationRequest *cr) const noexcept {
1206  size_t ans = 0;
1207  size_t p1 = 4111, p2 = 26951;
1208  IoSpecificationHasher io_hasher;
1209  std::vector<IoSpecification>::const_iterator itr = cr->inputs.begin(),
1210  end = cr->inputs.end();
1211  for (; itr != end; ++itr)
1212  ans = ans * p1 + io_hasher(*itr);
1213  itr = cr->outputs.begin();
1214  end = cr->outputs.end();
1215  for (; itr != end; ++itr)
1216  ans = ans * p2 + io_hasher(*itr);
1217  return ans;
1218 }
1219 
1220 
1221 
1222 } // namespace nnet3
1223 } // namespace kaldi
CommandType
CommandType is an enum that describes the category of the command used in the NnetComputation.
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void WriteIndexVector(std::ostream &os, bool binary, const std::vector< Index > &vec)
Definition: nnet-common.cc:126
void Write(std::ostream &ostream, bool binary) const
bool store_component_stats
you should set need_component_stats to true if you need the average-activation and average-derivative...
void WriteIntegerPairVector(std::ostream &os, bool binary, const std::vector< std::pair< T, T > > &v)
Function for writing STL vectors of pairs of integer types.
Definition: io-funcs-inl.h:93
std::vector< MatrixDebugInfo > matrix_debug_info
bool need_model_derivative
if need_model_derivative is true, then we&#39;ll be doing either model training or model-derivative compu...
const std::string & GetNodeName(int32 node_index) const
returns individual node name.
Definition: nnet-nnet.cc:684
static void GetIndexesStrings(const Nnet &nnet, const NnetComputation &computation, std::vector< std::string > *indexes_strings)
MiscComputationInfo misc_info
misc_info is for extensibility to things that don&#39;t easily fit into the framework.
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
void Read(std::istream &istream, bool binary)
bool operator==(const SubMatrixInfo &other) const
void ReadCindexVector(std::istream &is, bool binary, std::vector< Cindex > *vec)
Definition: nnet-common.cc:309
void PrintIndexes(std::ostream &os, const std::vector< Index > &indexes)
this will only be used for pretty-printing.
Definition: nnet-common.cc:442
int32 NewMatrix(int32 num_rows, int32 num_cols, MatrixStrideType stride_type)
Convenience function used when adding new matrices.
NnetComputation & operator=(const NnetComputation &other)
bool NeedDerivatives() const
returns true if any of inputs[*].has_deriv is true, or need_model_derivative is true.
void Print(std::ostream &os, const Nnet &nnet) const
void Write(std::ostream &ostream, bool binary) const
void swap(basic_filebuf< CharT, Traits > &x, basic_filebuf< CharT, Traits > &y)
kaldi::int32 int32
void Print(std::ostream &os) const
This function is for printing in a human-readable way, for debugging.
void ReadToken(std::istream &is, bool binary, std::string *str)
ReadToken gets the next token and puts it in str (exception on failure).
Definition: io-funcs.cc:154
std::vector< IoSpecification > inputs
std::vector< MatrixInfo > matrices
bool operator==(const ComputationRequest &other) const
std::vector< Command > commands
A hashing function object for strings.
Definition: stl-utils.h:248
void Write(std::ostream &ostream, bool binary) const
void Write(std::ostream &ostream, bool binary) const
void ReadIntegerPairVector(std::istream &is, bool binary, std::vector< std::pair< T, T > > *v)
Function for reading STL vector of pairs of integer types.
Definition: io-funcs-inl.h:131
The two main classes defined in this header are struct ComputationRequest, which basically defines a ...
void GetWholeSubmatrices(std::vector< int32 > *whole_submatrices) const
int32 NewSubMatrix(int32 base_submatrix, int32 row_offset, int32 num_rows, int32 col_offset, int32 num_cols)
Convenience function used when adding new sub-matrices.
void WriteCindexVector(std::ostream &os, bool binary, const std::vector< Cindex > &vec)
Definition: nnet-common.cc:282
void GetCommandStrings(const Nnet &nnet, std::string *preamble, std::vector< std::string > *command_strings) const
std::vector< CuArray< int32 > > indexes_cuda
void Read(std::istream &istream, bool binary)
void ReadIntegerVector(std::istream &is, bool binary, std::vector< T > *v)
Function for reading STL vector of integer types.
Definition: io-funcs-inl.h:232
static void ExpectToken(const std::string &token, const std::string &what_we_are_parsing, const std::string **next_token)
std::vector< std::vector< std::pair< int32, int32 > > > indexes_multi
void Write(std::ostream &ostream, bool binary) const
void Read(std::istream &istream, bool binary)
void Read(std::istream &istream, bool binary)
std::vector< SubMatrixInfo > submatrices
virtual void Write(std::ostream &os, bool binary) const =0
MatrixStrideType
Definition: matrix-common.h:44
void Read(std::istream &istream, bool binary)
#define KALDI_ERR
Definition: kaldi-error.h:147
void Swap(IoSpecification *other)
#define KALDI_WARN
Definition: kaldi-error.h:150
void PrintIntegerVector(std::ostream &os, const std::vector< int32 > &ints)
Definition: nnet-common.cc:525
std::vector< CuArray< Int32Pair > > indexes_ranges_cuda
const std::string & GetComponentName(int32 component_index) const
returns individual component name.
Definition: nnet-nnet.cc:689
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
bool operator==(const IoSpecification &other) const
int32 IndexForInput(const std::string &node_name) const
Returns the index into "inputs" corresponding to the node with name "node_name", or -1 if there is no...
void ReadIndexVector(std::istream &is, bool binary, std::vector< Index > *vec)
Definition: nnet-common.cc:143
static ComponentPrecomputedIndexes * ReadNew(std::istream &is, bool binary)
void PrintCindexes(std::ostream &ostream, const std::vector< Cindex > &cindexes, const std::vector< std::string > &node_names)
this will only be used for pretty-printing.
Definition: nnet-common.cc:498
std::string PrintCommand(int32 num_commands, int32 command)
std::vector< PrecomputedIndexesInfo > component_precomputed_indexes
static void PrintComputationPreamble(std::ostream &os, const NnetComputation &c, const Nnet &nnet, const std::vector< std::string > &submatrix_strings, const std::vector< std::string > &indexes_strings, const std::vector< std::string > &indexes_multi_strings)
size_t operator()(const IoSpecification &io_spec) const noexcept
std::vector< Index > indexes
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< IoSpecification > outputs
void WriteIntegerVector(std::ostream &os, bool binary, const std::vector< T > &v)
Function for writing STL vectors of integer types.
Definition: io-funcs-inl.h:198
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34
void Read(std::istream &istream, bool binary)
int32 IndexForOutput(const std::string &node_name) const
Returns the index into "inputs" corresponding to the node with name "node_name", or -1 if there is no...
std::vector< std::vector< int32 > > indexes
void Write(std::ostream &ostream, bool binary) const
void Read(std::istream &istream, bool binary)
void Print(std::ostream &os) const
This function is for printing info about the computation request in a human-readable way...
size_t operator()(const ComputationRequest *cr) const noexcept
bool IsWholeMatrix(int32 submatrix_index) const
void Print(std::ostream &os) const
const std::vector< std::string > & GetNodeNames() const
returns vector of node names (needed by some parsing code, for instance).
Definition: nnet-nnet.cc:63
static void GetIndexesMultiStrings(const Nnet &nnet, const NnetComputation &computation, std::vector< std::string > *indexes_multi_strings)
void Write(std::ostream &ostream, bool binary) const
void GetSubmatrixStrings(const Nnet &nnet, std::vector< std::string > *submat_strings) const
std::vector< std::vector< std::pair< int32, int32 > > > indexes_ranges