nnet-analyze.h
Go to the documentation of this file.
1 // nnet3/nnet-analyze.h
2 
3 // Copyright 2015-2017 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 #ifndef KALDI_NNET3_NNET_ANALYZE_H_
21 #define KALDI_NNET3_NNET_ANALYZE_H_
22 
23 #include "nnet3/nnet-compile.h"
24 
25 #include <iostream>
26 
27 namespace kaldi {
28 namespace nnet3 {
29 
30 
38 // This struct contains the attributes for a single command. See class
39 // ComputationVariables for the meaning of a variable, which can be identified
40 // with a sub-part of a matrix. Note, variables may be both read and written in
41 // the same command; e.g. for operations that do += or that write to only some
42 // elements of a variable (we can think of these as, for purposes of analysis,
43 // reading the remaining elements and writing them back.
45  // All of the vector variables below are made sorted and uniq by
46  // ComputeCommandAttributes.
47 
48  // variables read
49  std::vector<int32> variables_read;
50  // variables written
51  std::vector<int32> variables_written;
52 
53  // sub-matrices read (i.e. the submatrix appears in the command directly)
54  std::vector<int32> submatrices_read;
55  // sub-matrices written (i.e. the submatrix appears in the command directly)
56  std::vector<int32> submatrices_written;
57 
58  // matrices read
59  std::vector<int32> matrices_read;
60  // matrices written
61  std::vector<int32> matrices_written;
62 
63  // true if this command has side effects e.g. on the model (such as
64  // Backprop on an updatable component, or StoreStats).
66  CommandAttributes(): has_side_effects(false) { }
67 };
68 
69 
71 void PrintCommandAttributes(std::ostream &os,
72  const std::vector<CommandAttributes> &attributes);
73 
74 
75 enum AccessType {
79 };
80 
81 
122  public:
123  // This function must only be called once per object.
124  void Init(const NnetComputation &computation);
125 
126  // This function updates the CommandAttributes object to record an access of
127  // type read, write or read-write on the variables that this sub-matrix
128  // corresponds to, and also updates the matrices_accessed variable by adding
129  // the number of the underlying matrix. The slightly non-obvious thing it
130  // does is that if the access type is given as write, and the sub-matrix does
131  // not span the full row range of the matrix it belongs to (and hence does not
132  // span the full extent of the variables that we defined), the access is
133  // recorded as both read and write (because the result of the operation on
134  // those depends on the pre-existing contents, so it would not be correct to
135  // consider it just a write operation).
136  void RecordAccessForSubmatrix(
137  int32 submatrix_index,
138  AccessType access_type,
139  CommandAttributes *ca) const;
140 
143  void AppendVariablesForMatrix(
144  int32 matrix_index,
145  std::vector<int32> *variable_indexes) const;
146 
147 
148  // Appends to variable_indexes the sorted list of variables corresponding to a
149  // submatrix index.
150  void AppendVariablesForSubmatrix(
151  int32 submatrix_index,
152  std::vector<int32> *variable_indexes) const;
153 
154  // note: variables are zero-indexed.
155  int32 NumVariables() const { return num_variables_; }
156 
157  int32 GetMatrixForVariable(int32 variable) const;
158 
159  // returns a string that describes a variable in Matlab-like format (but with
160  // zero indexing): something like "m1" or "m1(0:99,:)" or "m1(0:19,10:49)"
161  std::string DescribeVariable(int32 variable) const;
162 
163  NnetComputation::SubMatrixInfo VariableInfo(int32 variable) const;
164  private:
165  // sets up split_points_, matrix_to_variable_index_, and num_variables_.
166  // called from constructor.
167  void ComputeSplitPoints(const NnetComputation &computation);
168  // sets up variables_for_submatrix_, is_full_matrix_, and submatrix_to_matrix_. called
169  // from constructor.
170  void ComputeVariablesForSubmatrix(const NnetComputation &computation);
171  // sets up variable_to_matrix_. called from constructor.
172  void ComputeVariableToMatrix();
173 
174  // This function assumes that 'sorted_vec' is sorted and unique, and that
175  // 'i' is an element of 'sorted_vec'; it returns the index of 'i' in vec,
176  // i.e. the k such that sorted_vec[k] == i.
177  static int32 FindIndexOf(const std::vector<int32> &sorted_vec, int32 i);
178 
179 
180  // Indexed first by matrix-index and then a list, this gives us all the split
181  // points at which column ranges start and end. For instance, if the 3'rd
182  // matrix has 20 columns and is split into ranges 0:9 and 10:19,
183  // split_points_[3] would equal [0, 10, 20]. column_split_points_[0] will
184  // always be empty because matrix-index zero is reserved for the empty matrix.
185  std::vector<std::vector<int32> > column_split_points_;
186  // This is as column_split_points_, except for row indexes instead of column
187  // indexes.
188  std::vector<std::vector<int32> > row_split_points_;
189 
190  // Maps from the matrix-index (note, zero is invalid as it corresponds to the
191  // empty matrix) to the variable-index for its first split point. for coding
192  // convenience there is one extra element at the end, which is equal to the
193  // total number of variables.
194  // For each matrix m, the matrix has num-row-variables * num-column-variables
195  // variables in total, where num-row-variables = row_split_points_[m].size() - 1, and
196  // num-column-variables = column_split_points_[m].size() - 1.
197  std::vector<int32> matrix_to_variable_index_;
198 
199  std::vector<int32> submatrix_to_matrix_;
200  // indexed by submatrix index, this is true if the submatrix spans the full
201  // row and column range of the underlying matrix. Affects whether write operations
202  // should be classed as write operations or as read-write operations.
203  std::vector<bool> submatrix_is_whole_matrix_;
204 
205 
206  // records the matrix index underlying each variable.
207  std::vector<int32> variable_to_matrix_;
208 
210 
211 
212  // For each submatrix, a list of the variables underlying it.
213  std::vector<std::vector<int32> > variables_for_submatrix_;
214 
215 
216 };
217 
218 
219 // This struct records an access to a variable (i.e. a row and column range of a
220 // matrix).
221 struct Access {
224  Access(int32 command_index, AccessType access_type):
225  command_index(command_index), access_type(access_type) { }
226  bool operator < (const Access &other) const {
227  return command_index < other.command_index;
228  }
229 };
230 
231 
244  const ComputationVariables &variables,
245  const std::vector<CommandAttributes> &command_attributes,
246  std::vector<std::vector<Access> > *variable_accesses);
247 
248 
264  std::vector<Access> accesses;
267  bool is_input;
270  bool is_output;
271  MatrixAccesses(): allocate_command(-1), deallocate_command(-1),
272  is_input(false), is_output(false) { }
273 };
274 
282  const Nnet &nnet,
283  const NnetComputation &computation,
284  const ComputationVariables &variables,
285  const std::vector<CommandAttributes> &command_attributes,
286  std::vector<MatrixAccesses> *matrix_accesses);
287 
289 void PrintMatrixAccesses(std::ostream &os,
290  const std::vector<MatrixAccesses> &matrix_accesses);
291 
294 struct Analyzer {
296  std::vector<CommandAttributes> command_attributes;
297  std::vector<std::vector<Access> > variable_accesses;
298  std::vector<MatrixAccesses> matrix_accesses;
299  void Init(const Nnet &nnet, const NnetComputation &computation);
300 };
301 
302 
309  public:
314  const Analyzer &analyzer): computation_(computation),
315  analyzer_(analyzer) { }
316 
323  int32 FirstNontrivialAccess(int32 s) const;
324 
330  int32 FirstAccess(int32 s) const;
331 
335  int32 LastAccess(int32 s) const;
336 
341  int32 LastWriteAccess(int32 s) const;
342 
348  int32 DataInvalidatedCommand(int32 c, int32 s) const;
349 
355  int32 FirstNontrivialMatrixAccess(int32 m) const;
356 
360  int32 LastMatrixAccess(int32 m) const;
361 
362  private:
365 };
366 
367 
372 void ComputeMatrixToSubmatrix(const NnetComputation &computation,
373  std::vector<std::vector<int32> > *mat_to_submat);
374 
375 
380 int32 MaxMemoryUsage(const NnetComputation &computation);
381 
382 
383 // computes a vector of attributes, one for each Command in the computation.
385  const Nnet &nnet,
386  const NnetComputation &computation,
387  const ComputationVariables &variables,
388  std::vector<CommandAttributes> *attributes);
389 
390 
392  // do the check_rewrite check only for a non-optimized computation, it may
393  // legitimately fail after optimization. see code for details.
395  // If 'check_unused_variables' is true, it checks for unused variables
396  // (e.g. unused parts of matrices). We only set it false for online
397  // computations, where there can be instances where a part of a matrix is
398  // apparently never accessed (until we consider that the matrix is swapped
399  // with another).
401 
403  check_rewrite(false), check_unused_variables(true) { }
404 };
405 
406 
407 // Note: this checker class does not work for online computations (that have a
408 // kGoto statement), but the function CheckComputation() is able to detect such
409 // computations and modify them in such a way that they can be checked by this
410 // class (and then do extra checks).
412  public:
414  const Nnet &nnet,
415  const NnetComputation &computation);
416  void Check(); // call this only once.
417  private:
418  // Various dimension consistency checks and checks on properties.
419  void CheckComputationIndexes() const;
420  // Checks for a situation where an undefined variable is read.
421  void CheckComputationUndefined() const;
422  // Checks that all writes are done before reads. details with implementation.
423  void CheckComputationRewrite() const;
424  // Check matrix accesses make sense.
425  void CheckComputationMatrixAccesses() const;
426  // Some checks related to the kCompressMatrix and kDecompressMatrix commands.
427  void CheckComputationCompression() const;
428  // Check debug_info has the correct size, if used.
429  void CheckComputationDebugInfo() const;
430 
432  const Nnet &nnet_;
435 };
436 
437 
440 void GetCommandsOfType(const NnetComputation &computation,
441  CommandType t,
442  std::vector<int32> *command_indexes);
443 
448 void CheckComputation(const Nnet &nnet,
449  const NnetComputation &computation,
450  bool check_rewrite = false);
451 
452 // This function returns the maximum amount of memory (in bytes) that the
453 // computation uses at any point (this would be GPU memory if the computation
454 // were using a GPU). This is based on allocations and deallocations of
455 // matrices, and input commands; it ignores any temporary allocation done inside
456 // Propagate() and Backprop() or other similar functions; it ignores precomputed
457 // indexes and other things residing in the computation; and of course it
458 // ignores things you might do with the output, such as the forward-backward
459 // code for chain computation.
460 int64 GetMaxMemoryUse(const NnetComputation &computation);
461 
462 
463 } // namespace nnet3
464 } // namespace kaldi
465 
466 
467 #endif
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 GetCommandsOfType(const NnetComputation &computation, CommandType t, std::vector< int32 > *command_indexes)
This utility function works out from a computation, the command-indexes of the commands of the given ...
int32 MaxMemoryUsage(const NnetComputation &computation)
Returns the total memory, in bytes, used by the computation (just the temporary memory, not counting the memory used by the nnet itself).
void PrintMatrixAccesses(std::ostream &os, const std::vector< MatrixAccesses > &matrix_accesses)
This function is to be used in debugging; it produces human-readable output.
ComputationAnalysis(const NnetComputation &computation, const Analyzer &analyzer)
This class stores the const references provided to its constructor -> be careful about changing them ...
Definition: nnet-analyze.h:313
bool is_output
true if this matrix is an output of the computation (i.e.
Definition: nnet-analyze.h:270
void PrintCommandAttributes(std::ostream &os, const std::vector< CommandAttributes > &attributes)
This function is to be used in debugging; it produces human-readable output.
std::vector< int32 > submatrix_to_matrix_
Definition: nnet-analyze.h:199
kaldi::int32 int32
void ComputeCommandAttributes(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &vars, std::vector< CommandAttributes > *attributes)
std::vector< CommandAttributes > command_attributes
Definition: nnet-analyze.h:296
const NnetComputation & computation_
Definition: nnet-analyze.h:433
std::vector< int32 > submatrices_written
Definition: nnet-analyze.h:56
std::vector< Access > accesses
Records the indexes of commands that access the matrix, and the type (read, read/write, write).
Definition: nnet-analyze.h:264
std::vector< int32 > matrices_read
Definition: nnet-analyze.h:59
std::vector< std::vector< int32 > > row_split_points_
Definition: nnet-analyze.h:188
std::vector< int32 > variables_written
Definition: nnet-analyze.h:51
std::vector< std::vector< int32 > > variables_for_submatrix_
Definition: nnet-analyze.h:213
int64 GetMaxMemoryUse(const NnetComputation &computation)
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
std::vector< int32 > variable_to_matrix_
Definition: nnet-analyze.h:207
std::vector< int32 > matrix_to_variable_index_
Definition: nnet-analyze.h:197
void ComputeVariableAccesses(const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< std::vector< Access > > *variable_accesses)
After the command-level attributes have been computed, this function organizes them per variable (see...
const CheckComputationOptions & config_
Definition: nnet-analyze.h:431
Access(int32 command_index, AccessType access_type)
Definition: nnet-analyze.h:224
std::vector< std::vector< Access > > variable_accesses
Definition: nnet-analyze.h:297
std::vector< std::vector< int32 > > column_split_points_
Definition: nnet-analyze.h:185
int32 deallocate_command
Index of the command that deallocates the matrix (which will be of type kDeallocMatrix or kSwapMatrix...
Definition: nnet-analyze.h:257
std::vector< int32 > submatrices_read
Definition: nnet-analyze.h:54
std::vector< int32 > matrices_written
Definition: nnet-analyze.h:61
AccessType access_type
Definition: nnet-analyze.h:223
bool operator<(const Int32Pair &a, const Int32Pair &b)
Definition: cu-matrixdim.h:83
const NnetComputation & computation_
Definition: nnet-analyze.h:363
void ComputeMatrixToSubmatrix(const NnetComputation &computation, std::vector< std::vector< int32 > > *mat_to_submat)
This function computes a vector &#39;mat_to_submat&#39;, indexed by matrix index, such that (*mat_to_submat)[...
void ComputeMatrixAccesses(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &variables, const std::vector< CommandAttributes > &command_attributes, std::vector< MatrixAccesses > *matrix_accesses)
This function organizes information in the CommandAttributes in a way that is convenient to access pe...
std::vector< MatrixAccesses > matrix_accesses
Definition: nnet-analyze.h:298
void CheckComputation(const Nnet &nnet, const NnetComputation &computation, bool check_rewrite)
This is a convenience interface for class ComputationChecker.
int32 allocate_command
Index of the command that allocates the matrix (which will be of type kAllocMatrix or kSwapMatrix)...
Definition: nnet-analyze.h:253
bool is_input
true if this matrix is an input to the computation (i.e.
Definition: nnet-analyze.h:267
std::vector< int32 > variables_read
Definition: nnet-analyze.h:49
ComputationVariables variables
Definition: nnet-analyze.h:295
std::vector< bool > submatrix_is_whole_matrix_
Definition: nnet-analyze.h:203
This struct exists to set up various pieces of analysis; it helps avoid the repetition of code where ...
Definition: nnet-analyze.h:294
This class performs various kinds of specific analysis on top of what class Analyzer gives you immedi...
Definition: nnet-analyze.h:308