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 400 of file nnet-analyze.h.

Constructor & Destructor Documentation

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

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

553  :
554  config_(config), nnet_(nnet), computation_(computation) { }
const NnetComputation & computation_
Definition: nnet-analyze.h:421
const CheckComputationOptions & config_
Definition: nnet-analyze.h:419

Member Function Documentation

void Check ( )

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

558  {
566 
567 }
void CheckComputationMatrixAccesses() const
const NnetComputation & computation_
Definition: nnet-analyze.h:421
void Init(const Nnet &nnet, const NnetComputation &computation)
const CheckComputationOptions & config_
Definition: nnet-analyze.h:419
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 960 of file nnet-analyze.cc.

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

Referenced by ComputationChecker::Check().

960  {
961  if (computation_.matrix_debug_info.empty()) return;
962  if (computation_.matrix_debug_info.size() !=
963  computation_.matrices.size())
964  KALDI_ERR << "Debug info has wrong size";
965  for (size_t i = 1; i < computation_.matrix_debug_info.size(); i++) {
966  if (computation_.matrix_debug_info[i].cindexes.size() !=
967  static_cast<size_t>(computation_.matrices[i].num_rows))
968  KALDI_ERR << "Debug info for matrix m" << i
969  << " has wrong num-rows.";
970  std::vector<Cindex>::const_iterator
971  iter = computation_.matrix_debug_info[i].cindexes.begin(),
972  end = computation_.matrix_debug_info[i].cindexes.end();
973  for (; iter != end; ++iter) {
974  if (iter->second.n < 0) {
975  KALDI_ERR << "Negative n index in debug info";
976  }
977  }
978  }
979 }
std::vector< MatrixDebugInfo > matrix_debug_info
std::vector< MatrixInfo > matrices
const NnetComputation & computation_
Definition: nnet-analyze.h:421
#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 684 of file nnet-analyze.cc.

References 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::kAllocMatrixFromOther, kaldi::nnet3::kAllocMatrixFromOtherZeroed, kaldi::nnet3::kAllocMatrixUndefined, kaldi::nnet3::kAllocMatrixZeroed, 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::kSimpleComponent, kaldi::nnet3::kUpdatableComponent, kaldi::nnet3::kUsesMemo, ComputationChecker::nnet_, Nnet::NumComponents(), Component::OutputDim(), Component::Properties(), and NnetComputation::submatrices.

Referenced by ComputationChecker::Check().

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

References ComputationChecker::a_, MatrixAccesses::accesses, MatrixAccesses::allocate_command, MatrixAccesses::deallocate_command, MatrixAccesses::is_input, KALDI_ERR, KALDI_WARN, and Analyzer::matrix_accesses.

Referenced by ComputationChecker::Check().

641  {
642  int32 num_matrices = a_.matrix_accesses.size();
643 
644  for (int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
645  const MatrixAccesses &accesses = a_.matrix_accesses[matrix_index];
646  if (accesses.allocate_command == -1)
647  KALDI_ERR << "Matrix m" << matrix_index << " is not initialized.";
648  if (accesses.accesses.empty()) {
649  KALDI_ERR << "Matrix m" << matrix_index << " is never accessed.";
650  } else if (accesses.accesses.front().command_index <
651  accesses.allocate_command) {
652  KALDI_ERR << "Matrix m" << matrix_index << " is accessed before "
653  "it is initialized";
654  }
655 
656  if (accesses.accesses.empty()) {
657  if (accesses.is_input) {
658  // we allow there to be no accesses if it is an input, e.g. if an
659  // output derivative is supplied for some reason but never used.
660  // We'll warn, though (once).
662  KALDI_WARN << "Matrix m" << matrix_index << " is never accessed. "
663  "Allowing because it is an input (un-needed input or "
664  "derivative?) Will warn only once.";
666  }
667  } else {
668  KALDI_ERR << "Matrix m" << matrix_index << " is never accessed.";
669  }
670  } else if (accesses.deallocate_command != -1 &&
671  accesses.accesses.back().command_index >=
672  accesses.deallocate_command) {
673  KALDI_ERR << "Matrix m" << matrix_index << " is accessed after "
674  "it is destroyed";
675  }
676  }
677 }
#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:296
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 577 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().

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

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

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

615  {
616  int32 num_variables = a_.variable_accesses.size();
617  for (int32 v = 0; v < num_variables; v++) {
618  const std::vector<Access> &accesses = a_.variable_accesses[v];
619  if (accesses.empty()) {
621  KALDI_ERR << "Variable " << v << " == "
622  << a_.variables.DescribeVariable(v) << "is never used.";
623  }
624  } else {
625  if (accesses[0].access_type != kWriteAccess)
626  KALDI_ERR << "Variable " << v << " == "
628  << " is read before it is written to";
629  }
630  }
631 }
std::string DescribeVariable(int32 variable) const
const CheckComputationOptions & config_
Definition: nnet-analyze.h:419
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< std::vector< Access > > variable_accesses
Definition: nnet-analyze.h:295
ComputationVariables variables
Definition: nnet-analyze.h:293

Member Data Documentation

const Nnet& nnet_
private

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