All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ComputationChecker Class Reference

#include <nnet-analyze.h>

Collaboration diagram for ComputationChecker:

Public Member Functions

 ComputationChecker (const CheckComputationOptions &config, const Nnet &nnet, const NnetComputation &computation)
 
void Check ()
 

Private Member Functions

void CheckComputationIndexes () const
 This very basic check just makes sure that all indexes in the commands are within range, that dimensions agree with the request, that row/column dimensions agree with component dimensions. More...
 
void CheckComputationUndefined () const
 Checks for the situation where a variable is read before being written. More...
 
void CheckComputationRewrite () const
 Checks for the situation where a read-only operation on a variable is followed by an operation that writes to the variable. More...
 
void CheckComputationMatrixAccesses () const
 
void CheckComputationDebugInfo () const
 

Private Attributes

const CheckComputationOptionsconfig_
 
const Nnetnnet_
 
const NnetComputationcomputation_
 
Analyzer a_
 

Detailed Description

Definition at line 403 of file nnet-analyze.h.

Constructor & Destructor Documentation

ComputationChecker ( const CheckComputationOptions config,
const Nnet nnet,
const NnetComputation computation 
)

Definition at line 546 of file nnet-analyze.cc.

549  :
550  config_(config), nnet_(nnet), computation_(computation) { }
const NnetComputation & computation_
Definition: nnet-analyze.h:423
const CheckComputationOptions & config_
Definition: nnet-analyze.h:421

Member Function Documentation

void Check ( )

Definition at line 554 of file nnet-analyze.cc.

References ComputationChecker::a_, CheckComputationOptions::check_rewrite, ComputationChecker::CheckComputationDebugInfo(), ComputationChecker::CheckComputationIndexes(), ComputationChecker::CheckComputationMatrixAccesses(), ComputationChecker::CheckComputationRewrite(), ComputationChecker::CheckComputationUndefined(), ComputationChecker::computation_, ComputationChecker::config_, Analyzer::Init(), and ComputationChecker::nnet_.

Referenced by kaldi::nnet3::CheckComputation(), kaldi::nnet3::CheckComputationOnline(), CachingOptimizingCompiler::CompileNoShortcut(), CachingOptimizingCompiler::ReadCache(), kaldi::nnet3::UnitTestNnetAnalyze(), kaldi::nnet3::UnitTestNnetCompute(), kaldi::nnet3::UnitTestNnetInputDerivatives(), and kaldi::nnet3::UnitTestNnetOptimizeWithOptions().

554  {
562 }
void CheckComputationMatrixAccesses() const
const NnetComputation & computation_
Definition: nnet-analyze.h:423
void Init(const Nnet &nnet, const NnetComputation &computation)
const CheckComputationOptions & config_
Definition: nnet-analyze.h:421
void CheckComputationIndexes() const
This very basic check just makes sure that all indexes in the commands are within range...
void CheckComputationUndefined() const
Checks for the situation where a variable is read before being written.
void CheckComputationRewrite() const
Checks for the situation where a read-only operation on a variable is followed by an operation that w...
void CheckComputationDebugInfo ( ) const
private

Definition at line 969 of file nnet-analyze.cc.

References ComputationChecker::computation_, rnnlm::i, KALDI_ERR, NnetComputation::matrices, and NnetComputation::matrix_debug_info.

Referenced by ComputationChecker::Check().

969  {
970  if (computation_.matrix_debug_info.empty()) return;
971  if (computation_.matrix_debug_info.size() !=
972  computation_.matrices.size())
973  KALDI_ERR << "Debug info has wrong size";
974  for (size_t i = 1; i < computation_.matrix_debug_info.size(); i++) {
975  if (computation_.matrix_debug_info[i].cindexes.size() !=
976  static_cast<size_t>(computation_.matrices[i].num_rows))
977  KALDI_ERR << "Debug info for matrix m" << i
978  << " has wrong num-rows.";
979  std::vector<Cindex>::const_iterator
980  iter = computation_.matrix_debug_info[i].cindexes.begin(),
981  end = computation_.matrix_debug_info[i].cindexes.end();
982  for (; iter != end; ++iter) {
983  if (iter->second.n < 0) {
984  KALDI_ERR << "Negative n index in debug info";
985  }
986  }
987  }
988 }
std::vector< MatrixDebugInfo > matrix_debug_info
std::vector< MatrixInfo > matrices
const NnetComputation & computation_
Definition: nnet-analyze.h:423
#define KALDI_ERR
Definition: kaldi-error.h:127
void CheckComputationIndexes ( ) const
private

This very basic check just makes sure that all indexes in the commands are within range, that dimensions agree with the request, that row/column dimensions agree with component dimensions.

Definition at line 686 of file nnet-analyze.cc.

References NnetComputation::Command::alpha, NnetComputation::Command::arg1, NnetComputation::Command::arg2, NnetComputation::Command::arg3, NnetComputation::Command::arg4, NnetComputation::Command::arg5, NnetComputation::Command::arg6, NnetComputation::Command::arg7, NnetComputation::Command::command_type, NnetComputation::commands, NnetComputation::component_precomputed_indexes, ComputationChecker::computation_, Nnet::GetComponent(), NnetComputation::indexes, NnetComputation::indexes_multi, NnetComputation::indexes_ranges, Component::InputDim(), Nnet::IsInputNode(), Nnet::IsOutputNode(), NnetComputation::IsWholeMatrix(), kaldi::nnet3::kAcceptInput, kaldi::nnet3::kAddRowRanges, kaldi::nnet3::kAddRows, kaldi::nnet3::kAddRowsMulti, kaldi::nnet3::kAddToRowsMulti, KALDI_ASSERT, KALDI_ERR, kaldi::nnet3::kAllocMatrix, kaldi::nnet3::kBackprop, kaldi::nnet3::kBackpropInPlace, kaldi::nnet3::kBackpropNeedsInput, kaldi::nnet3::kBackpropNeedsOutput, kaldi::nnet3::kBackpropNoModelUpdate, kaldi::nnet3::kCopyRows, kaldi::nnet3::kCopyRowsMulti, kaldi::nnet3::kCopyToRowsMulti, kaldi::nnet3::kDeallocMatrix, kaldi::nnet3::kGotoLabel, kaldi::nnet3::kMatrixAdd, kaldi::nnet3::kMatrixCopy, kaldi::nnet3::kNoOperation, kaldi::nnet3::kNoOperationLabel, kaldi::nnet3::kNoOperationMarker, kaldi::nnet3::kNoOperationPermanent, kaldi::nnet3::kPropagate, kaldi::nnet3::kPropagateInPlace, kaldi::nnet3::kProvideOutput, kaldi::nnet3::kSetConst, kaldi::nnet3::kSimpleComponent, kaldi::nnet3::kSwapMatrix, kaldi::nnet3::kUpdatableComponent, kaldi::nnet3::kUsesMemo, ComputationChecker::nnet_, Nnet::NumComponents(), Component::OutputDim(), Component::Properties(), and NnetComputation::submatrices.

Referenced by ComputationChecker::Check().

686  {
687  int32 num_commands = computation_.commands.size(),
688  num_submatrices = computation_.submatrices.size();
689  const std::vector<NnetComputation::SubMatrixInfo> &submatrices =
691 
692  // This maps from the memo-index > 0 to the Propagate command
693  // which created it. When the corresponding Backprop command
694  // is encountered, we delete the map element.
695  std::unordered_map<int32, int32> memo_to_command;
696 
697  for (int32 command_index = 0; command_index < num_commands; command_index++) {
698  const NnetComputation::Command &c = computation_.commands[command_index];
699  switch (c.command_type) {
700  case kAllocMatrix:
701  case kDeallocMatrix:
702  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
703  !computation_.IsWholeMatrix(c.arg1))
704  KALDI_ERR << "submatrix index out of range or invalid";
705  break;
706  case kSetConst:
707  if (c.arg1 < 1 || c.arg1 >= num_submatrices)
708  KALDI_ERR << "submatrix index out of range or invalid";
709  break;
710  case kSwapMatrix:
711  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
712  !computation_.IsWholeMatrix(c.arg1) ||
713  c.arg2 < 1 || c.arg2 >= num_submatrices ||
714  !computation_.IsWholeMatrix(c.arg2))
715  KALDI_ERR << "submatrix index out of range or invalid";
716  if (computation_.submatrices[c.arg1].num_rows !=
717  computation_.submatrices[c.arg2].num_rows ||
718  computation_.submatrices[c.arg1].num_cols !=
719  computation_.submatrices[c.arg2].num_cols)
720  KALDI_ERR << "Dimension mismatch in kSwapMatrix command";
721  break;
722  case kPropagate: {
723  if (c.arg1 < 0 || c.arg1 >= nnet_.NumComponents())
724  KALDI_ERR << "Component index out of range";
725  const Component *component = nnet_.GetComponent(c.arg1);
726  int32 properties = component->Properties();
727  if (c.arg2 < 0 ||
729  KALDI_ERR << "Precomputed-indexes index out of range";
730  if (c.arg2 != 0 && (properties & kSimpleComponent))
731  KALDI_ERR << "Precomputed-indexes index nonzero for simple component";
732  // note: input may be the empty matrix (in unusual circumstances, for non-simple
733  // components).
734  if (c.arg3 < 0 || c.arg3 >= num_submatrices ||
735  (c.arg3 == 0 && (properties & kSimpleComponent)) ||
736  c.arg4 < 1 || c.arg4 >= num_submatrices)
737  KALDI_ERR << "Sub-matrix indexes out of range.";
738  if (c.arg3 > 0 && submatrices[c.arg3].num_cols != component->InputDim())
739  KALDI_ERR << "Input-dim mismatch.";
740  if (submatrices[c.arg4].num_cols != component->OutputDim())
741  KALDI_ERR << "Input-dim mismatch.";
742  if ((properties & kSimpleComponent) &&
743  submatrices[c.arg3].num_rows !=
744  submatrices[c.arg4].num_rows)
745  KALDI_ERR << "Num-rows mismatch for simple component.";
746  if (!(properties & kPropagateInPlace) &&
747  c.arg3 == c.arg4)
748  KALDI_ERR << "In-place propagation not supported for this component";
749  if (c.arg5 > 0) {
750  KALDI_ASSERT(memo_to_command.count(c.arg5) == 0 &&
751  "Memo index re-used.");
752  memo_to_command[c.arg5] = command_index;
753  }
754  KALDI_ASSERT(c.arg6 == 0 || c.arg6 == 1);
755  break;
756  }
757  case kBackprop:
758  case kBackpropNoModelUpdate: {
759  if (c.arg1 < 0 || c.arg1 >= nnet_.NumComponents())
760  KALDI_ERR << "Component index in backprop invalid or out of range";
761  const Component *component = nnet_.GetComponent(c.arg1);
762  int32 properties = component->Properties();
763  if (c.arg2 < 0 ||
765  KALDI_ERR << "Precomputed-indexes index out of range";
766  if (c.arg2 != 0 && (properties & kSimpleComponent))
767  KALDI_ERR << "Precomputed-indexes index nonzero for simple component";
768  // output-deriv (arg5) must be supplied; others could plausibly be zero.
769  if (c.arg3 < 0 || c.arg3 >= num_submatrices ||
770  c.arg4 < 0 || c.arg4 >= num_submatrices ||
771  c.arg5 < 1 || c.arg5 >= num_submatrices ||
772  c.arg6 < 0 || c.arg6 >= num_submatrices)
773  KALDI_ERR << "Submatrix index out of range for backprop.";
774  if ((properties & kBackpropNeedsInput) && c.arg3 == 0)
775  KALDI_ERR << "Backprop input needed but not supplied.";
776  if ((properties & kBackpropNeedsOutput) && c.arg4 == 0)
777  KALDI_ERR << "Backprop output needed but not supplied.";
778  if (c.arg6 == 0 && !(properties && kUpdatableComponent)) {
779  // note: we could perhaps make this just a warning,
780  // or optimize it away somehow.
781  KALDI_ERR << "Backprop is done but has no effect.";
782  }
783  if (c.arg5 == c.arg6 && !(properties & kBackpropInPlace))
784  KALDI_ERR << "In-place backprop used where not supported.";
785  if (c.arg3 != 0 &&
786  submatrices[c.arg3].num_cols != component->InputDim())
787  KALDI_ERR << "Input-dim mismatch in backprop.";
788  if (c.arg4 != 0 &&
789  submatrices[c.arg4].num_cols != component->OutputDim())
790  KALDI_ERR << "Output-dim mismatch in backprop.";
791  if (c.arg5 != 0 &&
792  submatrices[c.arg5].num_cols != component->OutputDim())
793  KALDI_ERR << "Output-dim mismatch in backprop.";
794  if (c.arg6 != 0 &&
795  submatrices[c.arg6].num_cols != component->InputDim())
796  KALDI_ERR << "Input-dim mismatch in backprop.";
797  // check num-rows consistency for input.
798  if (c.arg3 != 0 && c.arg6 != 0 &&
799  submatrices[c.arg3].num_rows != submatrices[c.arg6].num_rows)
800  KALDI_ERR << "Num-rows mismatch in backprop input";
801  // check num-rows consistency for output
802  if (c.arg4 != 0 &&
803  submatrices[c.arg4].num_rows != submatrices[c.arg5].num_rows)
804  KALDI_ERR << "Num-rows mismatch in backprop output";
805  if ((properties & kSimpleComponent) && c.arg6 != 0 &&
806  submatrices[c.arg5].num_rows != submatrices[c.arg6].num_rows)
807  KALDI_ERR << "Num-rows mismatch in backprop input vs output.";
808  if (c.arg7 != 0) {
809  KALDI_ASSERT(c.arg7 > 0);
810  if (memo_to_command.count(c.arg7) == 0)
811  KALDI_ERR << "Memo-index " << c.arg7 << " not used for propagate.";
812  int32 propagate_command = memo_to_command[c.arg7];
813  memo_to_command.erase(c.arg7);
814  if (c.arg1 != computation_.commands[propagate_command].arg1)
815  KALDI_ERR << "Mismatch in component-node for memo index";
816  if (!(properties & kUsesMemo))
817  KALDI_ERR << "Component not expected to use a memo.";
818  }
819  break;
820  }
821  case kMatrixCopy:
822  case kMatrixAdd:
823  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
824  c.arg2 < 1 || c.arg2 >= num_submatrices)
825  KALDI_ERR << "Submatrix indexes out of range in matrix copy/add";
826  if (submatrices[c.arg1].num_rows != submatrices[c.arg2].num_rows ||
827  submatrices[c.arg1].num_cols != submatrices[c.arg2].num_cols)
828  KALDI_ERR << "Submatrix indexes out of range in matrix copy/add";
829  if (c.arg1 == c.arg2) {
830  // we allow copying to itself if alpha != 1.0; this is how we
831  // implement scaling.
832  if (!(c.command_type == kMatrixCopy && c.alpha != 1.0)) {
833  KALDI_ERR << "Adding/copying to self";
834  }
835  }
836  break;
837  case kAddRows:
838  case kCopyRows: {
839  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
840  c.arg2 < 1 || c.arg2 >= num_submatrices ||
841  static_cast<size_t>(c.arg3) >= computation_.indexes.size())
842  KALDI_ERR << "Index out of range in add-rows/copy-rows command.";
843  const std::vector<int32> &indexes = computation_.indexes[c.arg3];
844  if (indexes.size() != static_cast<size_t>(submatrices[c.arg1].num_rows))
845  KALDI_ERR << "Indexes size mismatch in add-rows/copy-rows";
846  if (submatrices[c.arg1].num_cols != submatrices[c.arg2].num_cols)
847  KALDI_ERR << "Dimension mismatch in add-rows/copy-rows";
848  if (*std::max_element(indexes.begin(), indexes.end()) >=
849  submatrices[c.arg2].num_rows)
850  KALDI_ERR << "Row-index out of range in add-rows/copy-rows";
851  if (c.arg1 == c.arg2)
852  KALDI_ERR << "Copying to self in add-rows/copy-rows command.";
853  break;
854  }
855  case kAddRowsMulti:
856  case kCopyRowsMulti:
857  case kAddToRowsMulti:
858  case kCopyToRowsMulti: {
859  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
860  static_cast<size_t>(c.arg2) >= computation_.indexes_multi.size())
861  KALDI_ERR << "Index out of range in *-multi command";
862  const std::vector<std::pair<int32, int32> > pairs =
863  computation_.indexes_multi[c.arg2];
864  int32 num_rows = submatrices[c.arg1].num_rows,
865  num_cols = submatrices[c.arg1].num_cols;
866  if (pairs.size() != static_cast<size_t>(num_rows))
867  KALDI_ERR << "Indexes dimension mismatch in *-multi command";
868  std::vector<std::pair<int32, int32> >::const_iterator
869  iter = pairs.begin(), end = pairs.end();
870  for (; iter != end; ++iter) {
871  int32 submatrix_index = iter->first, row_index = iter->second;
872  if (submatrix_index == -1) {
873  if (row_index != -1)
874  KALDI_ERR << "Expected -1 row index if submatrix index is -1";
875  } else {
876  if (submatrix_index < 1 || submatrix_index >= num_submatrices)
877  KALDI_ERR << "Submatrix index out of range in indexes_multi";
878  if (row_index < 0 ||
879  row_index >= submatrices[submatrix_index].num_rows)
880  KALDI_ERR << "Row index out of range in indexes_multi";
881  if (submatrix_index == c.arg1)
882  KALDI_ERR << "Copying from self in *-multi command.";
883  if (submatrices[submatrix_index].num_cols != num_cols)
884  KALDI_ERR << "Mismatching dimension in *-multi command";
885  }
886  }
887  if (c.command_type == kAddToRowsMulti ||
888  c.command_type == kCopyToRowsMulti) {
889  // check for duplicates; these are not allowed in kAddToRowsMulti
890  // or kCopyToRowsMulti because they would necessitate extra work
891  // in CUDA kernels.
892  std::vector<std::pair<int32, int32> > pairs_copy(pairs);
893  std::sort(pairs_copy.begin(), pairs_copy.end());
894  std::vector<std::pair<int32, int32> >::const_iterator
895  iter = pairs_copy.begin(), end = pairs_copy.end(),
896  next_iter;
897  for (; iter != end; ++iter) {
898  next_iter = iter;
899  ++next_iter;
900  if (next_iter != end && *iter == *next_iter &&
901  iter->first != -1) {
902  KALDI_ERR << "Duplicate element "
903  << iter->first << ',' << iter->second << " found in "
904  << "indexes for {add,copy}-to-rows-multi command.";
905  }
906  }
907  }
908  break;
909  }
910  case kAddRowRanges: {
911  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
912  c.arg2 < 1 || c.arg2 >= num_submatrices ||
913  static_cast<size_t>(c.arg3) >= computation_.indexes_ranges.size())
914  KALDI_ERR << "Index out of range in add-row-ranges command";
915  const std::vector<std::pair<int32, int32> > pairs =
917  if (static_cast<size_t>(submatrices[c.arg1].num_rows) != pairs.size())
918  KALDI_ERR << "Num-rows mismatch in add-row-ranges command";
919  if (submatrices[c.arg1].num_cols != submatrices[c.arg2].num_cols)
920  KALDI_ERR << "Dimension mismatch in add-row-ranges command";
921  int32 src_num_rows = submatrices[c.arg2].num_rows;
922  std::vector<std::pair<int32, int32> >::const_iterator
923  iter = pairs.begin(), end = pairs.end();
924  for (; iter != end; ++iter) {
925  if (!((iter->first == -1 && iter->second == -1) ||
926  (iter->second > iter->first &&
927  iter->first >= 0 && iter->second <= src_num_rows)))
928  KALDI_ERR << "Row range " << iter->first << ',' << iter->second
929  << " is invalid in add-row-ranges command.";
930  }
931  break;
932  }
933  case kAcceptInput: case kProvideOutput: {
934  if (c.arg1 < 1 || c.arg1 >= num_submatrices ||
935  !computation_.IsWholeMatrix(c.arg1))
936  KALDI_ERR << "submatrix index out of range or invalid";
937  // note: we may later change the following condition to allow component
938  // nodes. we allow it on output node because of derivatives.
939  if (!nnet_.IsInputNode(c.arg2) && !nnet_.IsOutputNode(c.arg2))
940  KALDI_ERR << "Invalid network node";
941  break;
942  }
943  case kNoOperation:
945  case kNoOperationMarker:
946  case kNoOperationLabel:
947  break;
948  case kGotoLabel: {
949  int32 label_index = c.arg1;
950  if (label_index < 0 || label_index >= command_index ||
951  computation_.commands[label_index].command_type != kNoOperationLabel)
952  KALDI_ERR << "kGotoLabel command has invalid destination index.";
953  if (command_index + 1 != num_commands) {
954  KALDI_ERR << "kGotoLabel is not the last command in the computation";
955  }
956  break;
957  }
958  default:
959  KALDI_ERR << "Unknown command type.";
960  }
961  }
962  if (!memo_to_command.empty()) {
963  KALDI_ERR << "Memo was used in command "
964  << memo_to_command.begin()->second
965  << " but never consumed.";
966  }
967 }
int32 NumComponents() const
Definition: nnet-nnet.h:124
bool IsOutputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kDescriptor and is not directly fo...
Definition: nnet-nnet.cc:112
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
Definition: nnet-nnet.cc:120
std::vector< Command > commands
const NnetComputation & computation_
Definition: nnet-analyze.h:423
bool IsWholeMatrix(int32 submatrix_index) const
std::vector< std::vector< std::pair< int32, int32 > > > indexes_multi
virtual int32 Properties() const =0
Return bitmask of the component's properties.
std::vector< SubMatrixInfo > submatrices
#define KALDI_ERR
Definition: kaldi-error.h:127
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
Definition: nnet-nnet.cc:150
std::vector< PrecomputedIndexesInfo > component_precomputed_indexes
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
std::vector< std::vector< int32 > > indexes
std::vector< std::vector< std::pair< int32, int32 > > > indexes_ranges
void CheckComputationMatrixAccesses ( ) const
private

Definition at line 636 of file nnet-analyze.cc.

References ComputationChecker::a_, MatrixAccesses::accesses, MatrixAccesses::allocate_command, NnetComputation::commands, ComputationChecker::computation_, MatrixAccesses::deallocate_command, MatrixAccesses::is_input, KALDI_ERR, KALDI_WARN, kaldi::nnet3::kSetConst, and Analyzer::matrix_accesses.

Referenced by ComputationChecker::Check().

636  {
637  int32 num_matrices = a_.matrix_accesses.size();
638 
639  for (int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
640  const MatrixAccesses &accesses = a_.matrix_accesses[matrix_index];
641  if (accesses.allocate_command == -1)
642  KALDI_ERR << "Matrix m" << matrix_index << " is not initialized.";
643  if (accesses.accesses.empty()) {
644  KALDI_ERR << "Matrix m" << matrix_index << " is never accessed.";
645  } else if (accesses.accesses.front().command_index <
646  accesses.allocate_command) {
647  KALDI_ERR << "Matrix m" << matrix_index << " is accessed before "
648  "it is initialized";
649  }
650  if (accesses.accesses.size() == 1) {
651  int32 first_access_command = accesses.accesses[0].command_index;
652  if (computation_.commands[first_access_command].command_type == kSetConst) {
653  KALDI_ERR << "Matrix m" << matrix_index << " is only set to a constant "
654  << "value, but then never accessed.";
655  }
656  }
657 
658  if (accesses.accesses.empty()) {
659  if (accesses.is_input) {
660  // we allow there to be no accesses if it is an input, e.g. if an
661  // output derivative is supplied for some reason but never used.
662  // We'll warn, though (once).
664  KALDI_WARN << "Matrix m" << matrix_index << " is never accessed. "
665  "Allowing because it is an input (un-needed input or "
666  "derivative?) Will warn only once.";
668  }
669  } else {
670  KALDI_ERR << "Matrix m" << matrix_index << " is never accessed.";
671  }
672  } else if (accesses.deallocate_command != -1 &&
673  accesses.accesses.back().command_index >=
674  accesses.deallocate_command) {
675  KALDI_ERR << "Matrix m" << matrix_index << " is accessed after "
676  "it is destroyed";
677  }
678  }
679 }
std::vector< Command > commands
const NnetComputation & computation_
Definition: nnet-analyze.h:423
#define KALDI_ERR
Definition: kaldi-error.h:127
#define KALDI_WARN
Definition: kaldi-error.h:130
std::vector< MatrixAccesses > matrix_accesses
Definition: nnet-analyze.h:297
static bool computation_checker_warned_unused_input
Checks that we never use variables before they are allocated or after they are deallocated, and some other checks that can be done from the MatrixAccesses.
void CheckComputationRewrite ( ) const
private

Checks for the situation where a read-only operation on a variable is followed by an operation that writes to the variable.

This should never occur prior to optimization, but after certain optimization we in effect "re-use" variables by doing things like propagate and backprop in-place, so this check shouldn't be performed after optimization.

Definition at line 572 of file nnet-analyze.cc.

References ComputationChecker::a_, CheckComputationOptions::check_unused_variables, ComputationChecker::config_, ComputationVariables::DescribeVariable(), KALDI_ERR, kaldi::nnet3::kReadAccess, Analyzer::variable_accesses, and Analyzer::variables.

Referenced by ComputationChecker::Check().

572  {
573  int32 num_variables = a_.variable_accesses.size();
574  for (int32 v = 0; v < num_variables; v++) {
575  const std::vector<Access> &accesses = a_.variable_accesses[v];
576  if (accesses.empty()) {
578  KALDI_ERR << "Variable " << v << " = " << a_.variables.DescribeVariable(v)
579  << " is never used.";
580  } else {
581  continue;
582  }
583  }
584  int32 num_accesses = accesses.size();
585  int32 first_pure_read = -1;
586  for (int32 access = 0; access < num_accesses; access++) {
587  if (accesses[access].access_type == kReadAccess) {
588  first_pure_read = access;
589  break;
590  }
591  }
592  if (first_pure_read != -1) {
593  for (int32 access = first_pure_read + 1;
594  access < num_accesses; access++) {
595  if (accesses[access].access_type != kReadAccess) {
596  KALDI_ERR << "Variable " << v << " = "
598  << " is modified after being read"
599  << " (this is not expected before optimization)";
600  }
601  }
602  }
603  }
604 }
std::string DescribeVariable(int32 variable) const
const CheckComputationOptions & config_
Definition: nnet-analyze.h:421
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< std::vector< Access > > variable_accesses
Definition: nnet-analyze.h:296
ComputationVariables variables
Definition: nnet-analyze.h:294
void CheckComputationUndefined ( ) const
private

Checks for the situation where a variable is read before being written.

Definition at line 610 of file nnet-analyze.cc.

References ComputationChecker::a_, CheckComputationOptions::check_unused_variables, ComputationChecker::config_, ComputationVariables::DescribeVariable(), KALDI_ERR, kaldi::nnet3::kWriteAccess, Analyzer::variable_accesses, and Analyzer::variables.

Referenced by ComputationChecker::Check().

610  {
611  int32 num_variables = a_.variable_accesses.size();
612  for (int32 v = 0; v < num_variables; v++) {
613  const std::vector<Access> &accesses = a_.variable_accesses[v];
614  if (accesses.empty()) {
616  KALDI_ERR << "Variable " << v << " == "
617  << a_.variables.DescribeVariable(v) << " is never used.";
618  }
619  } else {
620  if (accesses[0].access_type != kWriteAccess)
621  KALDI_ERR << "Variable " << v << " == "
623  << " is read before it is written to";
624  }
625  }
626 }
std::string DescribeVariable(int32 variable) const
const CheckComputationOptions & config_
Definition: nnet-analyze.h:421
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< std::vector< Access > > variable_accesses
Definition: nnet-analyze.h:296
ComputationVariables variables
Definition: nnet-analyze.h:294

Member Data Documentation

const Nnet& nnet_
private

The documentation for this class was generated from the following files: