34 for (
int32 submatrix_index = 1;
35 submatrix_index < num_submatrices;
44 for (
int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
50 computation.
matrices[matrix_index].num_cols);
53 computation.
matrices[matrix_index].num_rows);
61 for (
int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
64 num_variables = num_row_variables * num_column_variables;
75 std::vector<int32>::const_iterator iter = std::lower_bound(
76 vec.begin(), vec.end(),
i);
78 return iter - vec.begin();
93 for (
int32 submatrix_index = 1;
94 submatrix_index < num_submatrices;
109 KALDI_ASSERT(row_end > row_start && col_end > col_start &&
110 col_end <= num_column_variables);
112 for (
int32 r = row_start; r < row_end; r++)
113 for (
int32 c = col_start; c < col_end; c++)
114 variables.push_back(matrix_start_variable + r*num_column_variables + c);
115 if (row_start == 0 && row_end == num_row_variables &&
116 col_start == 0 && col_end == num_column_variables)
125 for (
int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
128 for (
int32 i = start_variable;
i < end_variable;
i++)
147 int32 submatrix_index,
148 std::vector<int32> *variable_indexes)
const {
151 variable_indexes->insert(variable_indexes->end(),
158 std::vector<int32> *variable_indexes)
const {
163 variable_indexes->reserve(variable_indexes->size() + end - start);
164 for (
int32 variable_index = start; variable_index < end; variable_index++)
165 variable_indexes->push_back(variable_index);
169 int32 submatrix_index,
172 if (submatrix_index == 0)
178 switch (access_type) {
193 if (!is_whole_matrix)
214 column_variable = offset % num_column_variables,
215 row_variable = offset / num_column_variables;
216 KALDI_ASSERT(column_variable >= 0 && row_variable >= 0 &&
217 row_variable < num_row_variables &&
218 column_variable < num_column_variables);
219 std::ostringstream os;
220 os <<
'm' << matrix_index;
221 if (num_row_variables != 1 || num_column_variables != 1) {
223 if (num_row_variables == 1) {
230 if (num_column_variables == 1) {
242 int32 variable)
const {
247 column_variable = offset % num_column_variables,
248 row_variable = offset / num_column_variables;
255 col_offset, num_cols);
265 const std::vector<std::pair<int32, int32> > &indexes_multi,
266 std::vector<int32> *submatrix_indexes) {
267 submatrix_indexes->clear();
268 std::vector<std::pair<int32, int32> >::const_iterator
269 iter = indexes_multi.begin(), end = indexes_multi.end();
270 int32 cur_submatrix_index = -1;
271 for (; iter != end; ++iter) {
272 int32 submatrix_index = iter->first;
273 if (submatrix_index != -1 && submatrix_index != cur_submatrix_index) {
274 cur_submatrix_index = submatrix_index;
275 submatrix_indexes->push_back(submatrix_index);
288 std::vector<CommandAttributes> *attributes) {
291 attributes->resize(num_commands);
292 for (
int32 command_index = 0; command_index < num_commands; command_index++) {
336 const std::vector<int32> &indexes = computation.
indexes[c.
arg3];
340 if (
std::count(indexes.begin(), indexes.end(), -1) > 0)
349 std::vector<int32> submatrix_indexes;
352 for (
size_t i = 0;
i < submatrix_indexes.size();
i++)
358 std::vector<int32> submatrix_indexes;
364 for (
size_t i = 0;
i < submatrix_indexes.size();
i++)
374 std::vector<int32> submatrix_indexes;
377 for (
size_t i = 0;
i < submatrix_indexes.size();
i++)
423 const std::vector<CommandAttributes> &command_attributes,
424 std::vector<std::vector<Access> > *variable_accesses) {
426 num_commands = command_attributes.size();
427 variable_accesses->clear();
428 variable_accesses->resize(num_variables);
429 for (
int32 c = 0; c < num_commands; c++) {
433 std::vector<int32> all_variables;
436 all_variables.insert(all_variables.end(), attr.
variables_read.begin(),
442 std::vector<int32>::const_iterator iter = all_variables.begin(),
443 end = all_variables.end();
444 for (; iter != end; ++iter) {
445 int32 variable_index = *iter;
449 is_written = (!is_read ?
true :
453 if (is_read && is_written) {
454 (*variable_accesses)[variable_index].push_back(
456 }
else if (is_read) {
457 (*variable_accesses)[variable_index].push_back(
460 (*variable_accesses)[variable_index].push_back(
471 const std::vector<CommandAttributes> &command_attributes,
472 std::vector<MatrixAccesses> *matrix_accesses) {
474 num_commands = command_attributes.size();
475 matrix_accesses->clear();
476 matrix_accesses->resize(num_matrices);
477 for (
int32 c = 0; c < num_commands; c++) {
481 std::vector<int32> all_matrices;
484 all_matrices.insert(all_matrices.end(), attr.
matrices_read.begin(),
490 std::vector<int32>::const_iterator iter = all_matrices.begin(),
491 end = all_matrices.end();
492 for (; iter != end; ++iter) {
493 int32 matrix_index = *iter;
494 bool is_read = std::binary_search(attr.
matrices_read.begin(),
497 is_written = (!is_read ?
true :
501 if (is_read && is_written) {
502 (*matrix_accesses)[matrix_index].accesses.push_back(
504 }
else if (is_read) {
505 (*matrix_accesses)[matrix_index].accesses.push_back(
508 (*matrix_accesses)[matrix_index].accesses.push_back(
515 int32 matrix_index1, matrix_index2;
520 KALDI_ERR <<
"Command does not operate on whole matrix";
522 if ((*matrix_accesses)[matrix_index1].allocate_command != -1)
523 KALDI_ERR <<
"Matrix " << matrix_index1 <<
" initialized twice.";
524 (*matrix_accesses)[matrix_index1].allocate_command = c;
528 KALDI_ERR <<
"Command does not operate on whole matrix";
532 if ((*matrix_accesses)[matrix_index1].allocate_command != -1)
533 KALDI_ERR <<
"Matrix " << matrix_index1 <<
" initialized twice.";
534 (*matrix_accesses)[matrix_index1].allocate_command = c;
535 if ((*matrix_accesses)[matrix_index2].deallocate_command != -1)
536 KALDI_ERR <<
"Matrix " << matrix_index2 <<
" destroyed twice.";
537 (*matrix_accesses)[matrix_index2].deallocate_command = c;
541 KALDI_ERR <<
"Command does not operate on whole matrix";
543 if ((*matrix_accesses)[matrix_index1].deallocate_command != -1)
544 KALDI_ERR <<
"Matrix " << matrix_index1 <<
" destroyed twice.";
545 (*matrix_accesses)[matrix_index1].deallocate_command = c;
549 KALDI_ERR <<
"Command does not operate on whole matrix";
551 (*matrix_accesses)[matrix_index1].is_input =
true;
555 if ((*matrix_accesses)[matrix_index1].allocate_command == -1)
556 (*matrix_accesses)[matrix_index1].allocate_command = c;
560 KALDI_ERR <<
"Command does not operate on whole matrix";
562 (*matrix_accesses)[matrix_index1].is_output =
true;
575 config_(config), nnet_(nnet), computation_(computation) { }
600 for (
int32 v = 0; v < num_variables; v++) {
602 if (accesses.empty()) {
605 <<
" is never used.";
610 int32 num_accesses = accesses.size();
611 int32 first_pure_read = -1;
612 for (
int32 access = 0; access < num_accesses; access++) {
614 first_pure_read = access;
618 if (first_pure_read != -1) {
619 for (
int32 access = first_pure_read + 1;
620 access < num_accesses; access++) {
624 <<
" is modified after being read" 625 <<
" (this is not expected before optimization)";
643 for (
int32 v = 0; v < num_variables; v++) {
645 if (accesses.empty()) {
669 <<
" is read before it is written to";
685 for (
int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
688 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is not initialized.";
690 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is never accessed.";
691 }
else if (accesses.
accesses.front().command_index <
693 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is accessed before " 697 int32 first_access_command = accesses.
accesses[0].command_index;
700 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is only set to a constant " 701 <<
"value, but then never accessed.";
710 if (!computation_checker_warned_unused_input) {
711 KALDI_WARN <<
"Matrix m" << matrix_index <<
" is never accessed. " 712 "Allowing because it is an input (un-needed input or " 713 "derivative?) Will warn only once.";
714 computation_checker_warned_unused_input =
true;
717 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is never accessed.";
720 accesses.
accesses.back().command_index >=
722 KALDI_ERR <<
"Matrix m" << matrix_index <<
" is accessed after " 733 int32 middle_command = -1;
736 middle_command =
static_cast<int32>(
i);
740 for (
int32 matrix_index = 1; matrix_index < num_matrices; matrix_index++) {
743 for (
int32 a = 0; a < num_accesses; a++) {
753 accesses.
accesses[a-1].command_index].command_type ==
759 int32 next_command_index = accesses.
accesses[a+1].command_index;
762 command_index < middle_command &&
763 next_command_index > middle_command);
764 if (command.
alpha == 0.0) {
771 num_accesses == a + 3);
774 int32 next_command_index = accesses.
accesses[a+2].command_index;
779 "RectifiedLinearComponent");
794 const std::vector<NnetComputation::SubMatrixInfo> &submatrices =
800 std::unordered_map<int32, int32> memo_to_command;
802 for (
int32 command_index = 0; command_index < num_commands; command_index++) {
807 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
809 KALDI_ERR <<
"submatrix index out of range or invalid";
812 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices)
813 KALDI_ERR <<
"submatrix index out of range or invalid";
816 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
818 c.
arg2 < 1 || c.
arg2 >= num_submatrices ||
820 KALDI_ERR <<
"submatrix index out of range or invalid";
825 KALDI_ERR <<
"Dimension mismatch in kSwapMatrix command";
829 KALDI_ERR <<
"Component index out of range";
834 KALDI_ERR <<
"Precomputed-indexes index out of range";
836 KALDI_ERR <<
"Precomputed-indexes index nonzero for simple component";
839 if (c.
arg3 < 0 || c.
arg3 >= num_submatrices ||
840 (c.
arg3 == 0 && (properties & kSimpleComponent)) ||
841 c.
arg4 < 1 || c.
arg4 >= num_submatrices)
842 KALDI_ERR <<
"Sub-matrix indexes out of range.";
847 if ((properties & kSimpleComponent) &&
848 submatrices[c.
arg3].num_rows !=
849 submatrices[c.
arg4].num_rows)
850 KALDI_ERR <<
"Num-rows mismatch for simple component.";
853 KALDI_ERR <<
"In-place propagation not supported for this component";
856 "Memo index re-used.");
857 memo_to_command[c.
arg5] = command_index;
865 KALDI_ERR <<
"Component index in backprop invalid or out of range";
870 KALDI_ERR <<
"Precomputed-indexes index out of range";
872 KALDI_ERR <<
"Precomputed-indexes index nonzero for simple component";
874 if (c.
arg3 < 0 || c.
arg3 >= num_submatrices ||
875 c.
arg4 < 0 || c.
arg4 >= num_submatrices ||
876 c.
arg5 < 1 || c.
arg5 >= num_submatrices ||
877 c.
arg6 < 0 || c.
arg6 >= num_submatrices)
878 KALDI_ERR <<
"Submatrix index out of range for backprop.";
880 KALDI_ERR <<
"Backprop input needed but not supplied.";
882 KALDI_ERR <<
"Backprop output needed but not supplied.";
886 KALDI_ERR <<
"Backprop is done but has no effect.";
889 KALDI_ERR <<
"In-place backprop used where not supported.";
892 KALDI_ERR <<
"Input-dim mismatch in backprop.";
895 KALDI_ERR <<
"Output-dim mismatch in backprop.";
898 KALDI_ERR <<
"Output-dim mismatch in backprop.";
901 KALDI_ERR <<
"Input-dim mismatch in backprop.";
904 submatrices[c.
arg3].num_rows != submatrices[c.
arg6].num_rows)
905 KALDI_ERR <<
"Num-rows mismatch in backprop input";
908 submatrices[c.
arg4].num_rows != submatrices[c.
arg5].num_rows)
909 KALDI_ERR <<
"Num-rows mismatch in backprop output";
910 if ((properties & kSimpleComponent) && c.
arg6 != 0 &&
911 submatrices[c.
arg5].num_rows != submatrices[c.
arg6].num_rows)
912 KALDI_ERR <<
"Num-rows mismatch in backprop input vs output.";
915 if (memo_to_command.count(c.
arg7) == 0)
916 KALDI_ERR <<
"Memo-index " << c.
arg7 <<
" not used for propagate.";
917 int32 propagate_command = memo_to_command[c.
arg7];
918 memo_to_command.erase(c.
arg7);
920 KALDI_ERR <<
"Mismatch in component-node for memo index";
922 KALDI_ERR <<
"Component not expected to use a memo.";
928 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
929 c.
arg2 < 1 || c.
arg2 >= num_submatrices)
930 KALDI_ERR <<
"Submatrix indexes out of range in matrix copy/add";
931 if (submatrices[c.
arg1].num_rows != submatrices[c.
arg2].num_rows ||
932 submatrices[c.
arg1].num_cols != submatrices[c.
arg2].num_cols)
933 KALDI_ERR <<
"Submatrix indexes out of range in matrix copy/add";
944 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
945 c.
arg2 < 1 || c.
arg2 >= num_submatrices ||
947 KALDI_ERR <<
"Index out of range in add-rows/copy-rows command.";
949 if (indexes.size() !=
static_cast<size_t>(submatrices[c.
arg1].num_rows))
950 KALDI_ERR <<
"Indexes size mismatch in add-rows/copy-rows";
951 if (submatrices[c.
arg1].num_cols != submatrices[c.
arg2].num_cols)
952 KALDI_ERR <<
"Dimension mismatch in add-rows/copy-rows";
953 if (*std::max_element(indexes.begin(), indexes.end()) >=
954 submatrices[c.
arg2].num_rows)
955 KALDI_ERR <<
"Row-index out of range in add-rows/copy-rows";
957 KALDI_ERR <<
"Copying to self in add-rows/copy-rows command.";
964 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
966 KALDI_ERR <<
"Index out of range in *-multi command";
967 const std::vector<std::pair<int32, int32> > pairs =
969 int32 num_rows = submatrices[c.
arg1].num_rows,
970 num_cols = submatrices[c.
arg1].num_cols;
971 if (pairs.size() !=
static_cast<size_t>(num_rows))
972 KALDI_ERR <<
"Indexes dimension mismatch in *-multi command";
973 std::vector<std::pair<int32, int32> >::const_iterator
974 iter = pairs.begin(), end = pairs.end();
975 for (; iter != end; ++iter) {
976 int32 submatrix_index = iter->first, row_index = iter->second;
977 if (submatrix_index == -1) {
979 KALDI_ERR <<
"Expected -1 row index if submatrix index is -1";
981 if (submatrix_index < 1 || submatrix_index >= num_submatrices)
982 KALDI_ERR <<
"Submatrix index out of range in indexes_multi";
984 row_index >= submatrices[submatrix_index].num_rows)
985 KALDI_ERR <<
"Row index out of range in indexes_multi";
986 if (submatrix_index == c.
arg1)
987 KALDI_ERR <<
"Copying from self in *-multi command.";
988 if (submatrices[submatrix_index].num_cols != num_cols)
989 KALDI_ERR <<
"Mismatching dimension in *-multi command";
997 std::vector<std::pair<int32, int32> > pairs_copy(pairs);
998 std::sort(pairs_copy.begin(), pairs_copy.end());
999 std::vector<std::pair<int32, int32> >::const_iterator
1000 iter = pairs_copy.begin(), end = pairs_copy.end(),
1002 for (; iter != end; ++iter) {
1005 if (next_iter != end && *iter == *next_iter &&
1006 iter->first != -1) {
1008 << iter->first <<
',' << iter->second <<
" found in " 1009 <<
"indexes for {add,copy}-to-rows-multi command.";
1016 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
1017 c.
arg2 < 1 || c.
arg2 >= num_submatrices ||
1019 KALDI_ERR <<
"Index out of range in add-row-ranges command";
1020 const std::vector<std::pair<int32, int32> > pairs =
1022 if (static_cast<size_t>(submatrices[c.
arg1].num_rows) != pairs.size())
1023 KALDI_ERR <<
"Num-rows mismatch in add-row-ranges command";
1024 if (submatrices[c.
arg1].num_cols != submatrices[c.
arg2].num_cols)
1025 KALDI_ERR <<
"Dimension mismatch in add-row-ranges command";
1026 int32 src_num_rows = submatrices[c.
arg2].num_rows;
1027 std::vector<std::pair<int32, int32> >::const_iterator
1028 iter = pairs.begin(), end = pairs.end();
1029 for (; iter != end; ++iter) {
1030 if (!((iter->first == -1 && iter->second == -1) ||
1031 (iter->second > iter->first &&
1032 iter->first >= 0 && iter->second <= src_num_rows)))
1033 KALDI_ERR <<
"Row range " << iter->first <<
',' << iter->second
1034 <<
" is invalid in add-row-ranges command.";
1039 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
1041 KALDI_ERR <<
"submatrix index out of range or invalid";
1044 KALDI_ERR <<
"Invalid compressed-matrix type.";
1046 KALDI_ERR <<
"Invalid 'truncate' option for compressing matrix.";
1049 KALDI_ERR <<
"Invalid alpha in kCompressMatrix command.";
1053 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
1055 KALDI_ERR <<
"submatrix index out of range or invalid";
1059 if (c.
arg1 < 1 || c.
arg1 >= num_submatrices ||
1061 KALDI_ERR <<
"submatrix index out of range or invalid";
1075 if (label_index < 0 || label_index >= command_index ||
1077 KALDI_ERR <<
"kGotoLabel command has invalid destination index.";
1078 if (command_index + 1 != num_commands) {
1079 KALDI_ERR <<
"kGotoLabel is not the last command in the computation";
1087 if (!memo_to_command.empty()) {
1088 KALDI_ERR <<
"Memo was used in command " 1089 << memo_to_command.begin()->second
1090 <<
" but never consumed.";
1098 KALDI_ERR <<
"Debug info has wrong size";
1103 <<
" has wrong num-rows.";
1104 std::vector<Cindex>::const_iterator
1107 for (; iter != end; ++iter) {
1108 if (iter->second.n < 0) {
1109 KALDI_ERR <<
"Negative n index in debug info";
1120 bool check_rewrite) {
1123 for (
int32 c = num_commands - 2;
1147 bool check_rewrite) {
1149 if (!computation.
commands.empty() &&
1160 computation.
Print(std::cerr, nnet);
1161 KALDI_ERR <<
"Computation check failed for computation printed above " 1162 "(actual error message is above computation)";
1168 std::vector<std::vector<int32> > *mat_to_submat) {
1171 mat_to_submat->clear();
1172 mat_to_submat->resize(num_matrices);
1173 for (
int32 submatrix_index = 1;
1174 submatrix_index < num_submatrices;
1175 submatrix_index++) {
1176 int32 matrix_index = computation.
submatrices[submatrix_index].matrix_index;
1177 KALDI_ASSERT(matrix_index > 0 && matrix_index < num_matrices);
1178 (*mat_to_submat)[matrix_index].push_back(submatrix_index);
1185 std::vector<int32> variable_indexes;
1186 analyzer_.variables.AppendVariablesForSubmatrix(s, &variable_indexes);
1187 std::vector<int32>::const_iterator iter = variable_indexes.begin(),
1188 end = variable_indexes.end();
1189 for (; iter != end; ++iter) {
1191 const std::vector<Access> &accesses = analyzer_.variable_accesses[v];
1192 std::vector<Access>::const_iterator access_iter = accesses.begin(),
1193 access_end = accesses.end();
1194 for (; access_iter != access_end; ++access_iter) {
1195 int32 command_index = access_iter->command_index;
1199 command.
alpha == 0.0)) {
1200 ans = std::min(ans, command_index);
1212 std::vector<int32> variable_indexes;
1213 analyzer_.variables.AppendVariablesForSubmatrix(s, &variable_indexes);
1214 std::vector<int32>::const_iterator iter = variable_indexes.begin(),
1215 end = variable_indexes.end();
1216 for (; iter != end; ++iter) {
1218 const std::vector<Access> &accesses = analyzer_.variable_accesses[v];
1219 if (!accesses.empty())
1220 ans = std::min(ans, accesses[0].command_index);
1229 const std::vector<Access> &accesses =
1230 analyzer_.matrix_accesses[m].accesses;
1231 std::vector<Access>::const_iterator access_iter = accesses.begin(),
1232 access_end = accesses.end();
1233 for (; access_iter != access_end; ++access_iter) {
1234 int32 command_index = access_iter->command_index;
1238 command.
alpha == 0.0)) {
1239 ans = std::min(ans, command_index);
1251 const std::vector<Access> &accesses =
1252 analyzer_.matrix_accesses[m].accesses;
1253 std::vector<Access>::const_reverse_iterator access_iter = accesses.rbegin(),
1254 access_end = accesses.rend();
1255 for (; access_iter != access_end; ++access_iter) {
1256 int32 command_index = access_iter->command_index;
1257 ans = std::max(ans, command_index);
1267 std::vector<int32> variable_indexes;
1268 analyzer_.variables.AppendVariablesForSubmatrix(s, &variable_indexes);
1269 std::vector<int32>::const_iterator iter = variable_indexes.begin(),
1270 end = variable_indexes.end();
1271 for (; iter != end; ++iter) {
1273 const std::vector<Access> &accesses = analyzer_.variable_accesses[v];
1275 std::vector<Access>::const_reverse_iterator access_iter = accesses.rbegin(),
1276 access_end = accesses.rend();
1277 for (; access_iter != access_end; ++access_iter) {
1278 int32 command_index = access_iter->command_index;
1283 ans = std::max(ans, command_index);
1294 if (analyzer_.matrix_accesses[matrix_index].is_output)
1297 std::vector<int32> variable_indexes;
1298 analyzer_.variables.AppendVariablesForSubmatrix(s, &variable_indexes);
1299 std::vector<int32>::const_iterator iter = variable_indexes.begin(),
1300 end = variable_indexes.end();
1301 for (; iter != end; ++iter) {
1303 const std::vector<Access> &accesses = analyzer_.variable_accesses[v];
1305 std::vector<Access>::const_reverse_iterator access_iter = accesses.rbegin(),
1306 access_end = accesses.rend();
1307 for (; access_iter != access_end; ++access_iter) {
1308 int32 command_index = access_iter->command_index;
1315 ans = std::max(ans, command_index);
1327 int32 ans = analyzer_.matrix_accesses[matrix_index].deallocate_command;
1330 std::vector<int32> variable_indexes;
1331 analyzer_.variables.AppendVariablesForSubmatrix(s, &variable_indexes);
1332 std::vector<int32>::const_iterator iter = variable_indexes.begin(),
1333 end = variable_indexes.end();
1334 for (; iter != end; ++iter) {
1336 const std::vector<Access> &accesses = analyzer_.variable_accesses[v];
1337 std::vector<Access>::const_iterator access_iter = accesses.begin(),
1338 access_end = accesses.end();
1339 for (; access_iter != access_end; ++access_iter) {
1340 int32 command_index = access_iter->command_index;
1341 if (command_index > c &&
1343 ans = std::min(ans, command_index);
1351 const std::vector<MatrixAccesses> &matrix_accesses) {
1352 int32 num_matrices = matrix_accesses.size();
1353 for (
int32 m = 1; m < num_matrices; m++) {
1358 std::vector<Access>::const_iterator iter = a.
accesses.begin(),
1360 for (; iter != end; ++iter)
1361 os <<
'c' << iter->command_index <<
"(" 1363 (iter->access_type ==
kWriteAccess ?
"w" :
"rw")) <<
") ";
1369 const std::vector<CommandAttributes> &attributes) {
1370 int32 num_commands = attributes.size();
1371 for (
int32 c = 0; c < num_commands; c++) {
1373 os <<
"c" << c <<
": ";
1376 std::vector<int32>::const_iterator iter = this_attr.
variables_read.begin(),
1378 for (; iter != end; ++iter) {
1380 if (iter+1 != end) os <<
",";
1386 std::vector<int32>::const_iterator
1389 for (; iter != end; ++iter) {
1391 if (iter+1 != end) os <<
",";
1397 std::vector<int32>::const_iterator iter = this_attr.
matrices_read.begin(),
1399 for (; iter != end; ++iter) {
1401 if (iter+1 != end) os <<
",";
1407 std::vector<int32>::const_iterator
1410 for (; iter != end; ++iter) {
1412 if (iter+1 != end) os <<
",";
1422 variables.Init(computation);
1431 std::vector<int32> *command_indexes) {
1433 command_indexes->clear();
1434 for (
int32 c = 0; c < num_commands; c++)
1435 if (computation.
commands[c].command_type == t)
1436 command_indexes->push_back(c);
1440 int64 cur_memory_use = 0,
1449 std::vector<int32> num_compressed_bytes(num_submatrices, -100000000);
1450 for (
int32 command_index = 0; command_index < num_commands; ++command_index) {
1452 int64 this_num_bytes = -100000000,
1453 this_compressed_num_bytes = -10000000;
1456 if (c.
arg1 >= 0 && c.
arg1 < num_submatrices) {
1460 this_num_bytes =
static_cast<int64
>(
sizeof(
BaseFloat)) *
1464 this_compressed_num_bytes =
1467 1 : 2) *
static_cast<int64
>(submat_info.
num_rows) *
1469 num_compressed_bytes[c.
arg1] = this_compressed_num_bytes;
1471 this_compressed_num_bytes = num_compressed_bytes[c.
arg1];
1477 cur_memory_use += this_num_bytes;
1480 cur_memory_use -= this_num_bytes;
1483 cur_memory_use += this_compressed_num_bytes - this_num_bytes;
1486 cur_memory_use += this_num_bytes - this_compressed_num_bytes;
1492 if (cur_memory_use > max_memory_use)
1493 max_memory_use = cur_memory_use;
1495 return max_memory_use;
void Init(const NnetComputation &computation)
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...
void AppendVariablesForMatrix(int32 matrix_index, std::vector< int32 > *variable_indexes) const
Appends to variables_indexes the sorted list of variables corresponding to a matrix index...
int32 FirstNontrivialAccess(int32 s) const
Returns the first command (read or write) that accesses any part of 's' except for zeroing it (i...
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 ...
ComputationChecker(const CheckComputationOptions &config, const Nnet &nnet, const NnetComputation &computation)
std::vector< MatrixDebugInfo > matrix_debug_info
void PrintMatrixAccesses(std::ostream &os, const std::vector< MatrixAccesses > &matrix_accesses)
This function is to be used in debugging; it produces human-readable output.
Abstract base-class for neural-net components.
void ComputeVariableToMatrix()
void CheckComputationMatrixAccesses() const
void PrintCommandAttributes(std::ostream &os, const std::vector< CommandAttributes > &attributes)
This function is to be used in debugging; it produces human-readable output.
void Print(std::ostream &os, const Nnet &nnet) const
std::vector< int32 > submatrix_to_matrix_
This file contains utilities for analyzing and checking computations, which are used in the optimizat...
bool IsInputNode(int32 node) const
Returns true if this is an output node, meaning that it is of type kInput.
void swap(basic_filebuf< CharT, Traits > &x, basic_filebuf< CharT, Traits > &y)
std::vector< MatrixInfo > matrices
virtual int32 OutputDim() const =0
Returns output-dimension of this component.
int32 GetMatrixForVariable(int32 variable) const
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
void ComputeCommandAttributes(const Nnet &nnet, const NnetComputation &computation, const ComputationVariables &vars, std::vector< CommandAttributes > *attributes)
std::vector< Command > commands
static void IndexesMultiToSubmatrixIndexes(const std::vector< std::pair< int32, int32 > > &indexes_multi, std::vector< int32 > *submatrix_indexes)
given a vector of pairs from computation.indexes_multi_indexes containing paris (submatrix-index, row-index), this function outputs to "submatrix_indexes" all (unique) submatrix indexes that appear; and it outputs to "contains_null_marker" true if the pair (-1, -1) appears anywhere in indexes_multi, and false otherwise.
int32 LastMatrixAccess(int32 m) const
Returns the last non-deallocation command that accesses any part of matrix 'm'; if there is no such c...
const NnetComputation & computation_
std::vector< int32 > submatrices_written
std::vector< Access > accesses
Records the indexes of commands that access the matrix, and the type (read, read/write, write).
std::vector< int32 > matrices_read
std::vector< std::vector< int32 > > row_split_points_
std::vector< int32 > variables_written
std::vector< std::vector< int32 > > variables_for_submatrix_
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.
std::vector< int32 > variable_to_matrix_
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...
std::vector< int32 > matrix_to_variable_index_
void Init(const Nnet &nnet, const NnetComputation &computation)
int32 NumVariables() const
std::vector< std::vector< std::pair< int32, int32 > > > indexes_multi
void CheckComputationIndexes() const
This very basic check just makes sure that all indexes in the commands are within range...
void CheckComputationRewrite() const
Checks for the situation where a read-only operation on a variable is followed by an operation that w...
virtual int32 Properties() const =0
Return bitmask of the component's properties.
void RecordAccessForSubmatrix(int32 submatrix_index, AccessType access_type, CommandAttributes *ca) const
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...
static int32 FindIndexOf(const std::vector< int32 > &sorted_vec, int32 i)
const CheckComputationOptions & config_
int32 FirstNontrivialMatrixAccess(int32 m) const
Returns the first command that is not a zeroing command (kSetConst with alpha=0.0), that accesses any part of 'm' [note: allocation and deallocation do not count a matrix accesses.
std::vector< SubMatrixInfo > submatrices
void CheckComputationCompression() const
int32 FirstAccess(int32 s) const
Returns the first command (read or write) that accesses any part of 's', including possibly zeroing i...
void CheckComputationDebugInfo() const
std::vector< std::vector< Access > > variable_accesses
std::vector< std::vector< int32 > > column_split_points_
void CheckComputationUndefined() const
Checks for the situation where a variable is read before being written.
int32 deallocate_command
Index of the command that deallocates the matrix (which will be of type kDeallocMatrix or kSwapMatrix...
std::vector< int32 > submatrices_read
int32 LastWriteAccess(int32 s) const
Returns the last command-index that accesses any part of submatrix 's' as a write operation...
bool check_unused_variables
void ComputeSplitPoints(const NnetComputation &computation)
int32 DataInvalidatedCommand(int32 c, int32 s) const
Returns (the first command-index after 'c' that any part of submatrix 's' is written to); or if there...
std::vector< int32 > matrices_written
int32 LastAccess(int32 s) const
Returns the last non-deallocation command that accesses any part of submatrix 's'; if there is no suc...
Component * GetComponent(int32 c)
Return component indexed c. Not a copy; not owned by caller.
NnetComputation::SubMatrixInfo VariableInfo(int32 variable) const
std::vector< PrecomputedIndexesInfo > component_precomputed_indexes
virtual std::string Type() const =0
Returns a string such as "SigmoidComponent", describing the type of the object.
void ComputeMatrixToSubmatrix(const NnetComputation &computation, std::vector< std::vector< int32 > > *mat_to_submat)
This function computes a vector 'mat_to_submat', 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
int32 NumComponents() const
void CheckComputation(const Nnet &nnet, const NnetComputation &computation, bool check_rewrite)
This is a convenience interface for class ComputationChecker.
static void CheckComputationOnline(const Nnet &nnet, NnetComputation computation, bool check_rewrite)
#define KALDI_ASSERT(cond)
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 ComputeVariablesForSubmatrix(const NnetComputation &computation)
void AppendVariablesForSubmatrix(int32 submatrix_index, std::vector< int32 > *variable_indexes) const
int32 allocate_command
Index of the command that allocates the matrix (which will be of type kAllocMatrix or kSwapMatrix)...
bool is_input
true if this matrix is an input to the computation (i.e.
std::vector< int32 > variables_read
std::vector< std::vector< int32 > > indexes
ComputationVariables variables
std::vector< bool > submatrix_is_whole_matrix_
virtual int32 InputDim() const =0
Returns input-dimension of this component.
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
bool IsWholeMatrix(int32 submatrix_index) const
std::string DescribeVariable(int32 variable) const
std::vector< std::vector< std::pair< int32, int32 > > > indexes_ranges