29 namespace time_height_convolution {
45 const std::vector<int32> &columns,
47 std::vector<std::vector<int32> > *backward_columns) {
48 int32 columns_dim = columns.size();
49 std::vector<std::vector<int32> > temp(input_dim);
50 for (
int32 i = 0;
i < columns_dim;
i++) {
58 int32 max_overlap = 0;
59 for (
int32 j = 0;
j < input_dim;
j++)
60 max_overlap = std::max(max_overlap,
61 static_cast<int32>(temp[
j].size()));
62 backward_columns->resize(max_overlap);
63 for (
int32 k = 0; k < max_overlap; k++) {
64 (*backward_columns)[k].clear();
65 (*backward_columns)[k].resize(input_dim, -1);
67 for (
int32 j = 0;
j < input_dim;
j++) {
68 for (
int32 k = 0; k < static_cast<int32>(temp[
j].size()); k++) {
70 (*backward_columns)[k][
j] =
i;
81 if (vec[
i+1] != vec[
i] + 1)
88 std::ostringstream os;
94 <<
", {time,height}-offsets=[";
99 os <<
"], required-time-offsets=[";
112 for (std::vector<Offset>::const_iterator iter =
offsets.begin();
119 int32 cur_offset = *iter;
121 int32 this_offset = *iter;
123 this_offset - cur_offset);
124 cur_offset = this_offset;
131 bool allow_height_padding)
const {
136 KALDI_WARN <<
"Convolution model fails basic check.";
141 if (!(temp == *
this)) {
142 KALDI_WARN <<
"Derived variables are incorrect.";
149 KALDI_WARN <<
"Required time offsets not a subset of all_time_offsets.";
154 std::vector<bool> h_in_used(
height_in,
false);
155 std::vector<bool> offsets_used(
offsets.size(),
false);
162 bool some_input_available =
false;
167 offsets_used[
i] =
true;
168 h_in_used[h_in] =
true;
170 some_input_available =
true;
172 if (!allow_height_padding) {
173 KALDI_WARN <<
"height padding not allowed but is required.";
178 if (!some_input_available) {
182 std::ostringstream os;
185 "no input is available, if only required time-indexes " 192 if (check_heights_used) {
195 KALDI_WARN <<
"The input at the " << h <<
"'th height is never used.";
200 for (
size_t i = 0;
i < offsets_used.size();
i++) {
201 if (!offsets_used[
i]) {
204 <<
") of this computation is never used.";
235 WriteToken(os, binary,
"<HeightSubsampleOut>");
238 std::vector<std::pair<int32, int32> > pairs(
offsets.size());
241 pairs[
i].second =
offsets[
i].height_offset;
246 WriteToken(os, binary,
"<RequiredTimeOffsets>");
248 WriteToken(os, binary,
"</ConvolutionModel>");
264 std::vector<std::pair<int32, int32> > pairs;
269 offsets[
i].height_offset = pairs[
i].second;
271 std::vector<int32> required_time_offsets_list;
276 required_time_offsets_list.end());
299 int32 num_steps = steps.size();
302 for (
int32 s = 0; s < num_steps; s++) {
333 steps.resize(num_steps);
334 for (
int32 s = 0; s < num_steps; s++) {
353 num_t_out > 0 && num_images > 0);
355 (temp_rows <= num_t_out * num_images &&
358 bool temp_mat_required =
false;
359 int32 num_steps = steps.size();
360 int32 num_extra_input_times = num_t_in - num_t_out,
362 smallest_time_shift = 1000,
363 largest_time_shift = 0;
365 for (
int32 s = 0; s < num_steps; s++) {
378 std::vector<int32> columns;
382 bool all_negative =
true;
384 bool contiguous =
true;
385 for (
int32 i = 0;
i < temp_height;
i++) {
396 all_negative =
false;
399 h * num_filters_in + f);
404 if (!contiguous || columns.size() != input_cols) {
407 temp_mat_required =
true;
412 std::vector<int32> columns_reconstructed(columns.size(), -1);
419 std::vector<int32> backward_columns;
424 int32 c = backward_columns[l];
428 columns_reconstructed[c] = l;
436 largest_time_shift == num_extra_input_times);
459 output_rows = output->
NumRows();
466 for (
int32 s = 0; s < num_steps; s++) {
472 input_row_start, output_rows,
484 temp_num_cols != input.
NumCols()) {
495 temp_num_cols, temp_num_cols);
503 temp_mat_part.CopyFromMat(input_part.ColRange(step.
first_column,
507 temp_mat_part.Data(), temp_mat_part.NumRows() * cc.
height_out,
511 params_part,
kTrans, 1.0);
514 input_part.Data(), input_part.NumRows() * cc.
height_out,
519 params_part,
kTrans, 1.0);
543 if (input_rows != required_input_rows) {
544 if (input_rows % required_input_rows != 0)
545 KALDI_ERR <<
"Input matrix has wrong size.";
549 multiple = input_rows / required_input_rows,
550 new_num_cols = num_cols * multiple,
551 new_stride = new_num_cols;
553 input.
Data(), required_input_rows, new_num_cols, new_stride);
573 t_start += num_time_steps_per_chunk) {
575 this_num_t_out = std::min<int32>(num_t_left,
576 num_time_steps_per_chunk),
577 this_num_t_in = this_num_t_out + num_extra_in;
588 &temp_part, &output_part);
614 output_rows = output_deriv.
NumRows();
621 for (
int32 s = 0; s < num_steps; s++) {
625 input_row_start, output_rows,
638 temp_num_cols != input_deriv->
NumCols()) {
650 temp_num_cols, temp_num_cols),
651 temp_mat_part_reshaped(
652 temp_mat_part.Data(), temp_mat_part.NumRows() * cc.
height_out,
668 num_cols).AddMat(1.0, temp_mat_part);
672 input_deriv_part.Data(), input_deriv_part.NumRows() * cc.
height_out,
701 if (input_rows != required_input_rows) {
702 if (input_rows % required_input_rows != 0)
703 KALDI_ERR <<
"Input matrix has wrong size.";
707 multiple = input_rows / required_input_rows,
708 new_num_cols = num_cols * multiple,
709 new_stride = new_num_cols;
711 input_deriv->
Data(), required_input_rows,
712 new_num_cols, new_stride);
732 t_start += num_time_steps_per_chunk) {
734 this_num_t_out = std::min<int32>(num_t_left,
735 num_time_steps_per_chunk),
736 this_num_t_in = this_num_t_out + num_extra_in;
749 &temp_part, &input_deriv_part);
754 &temp_mat, input_deriv);
775 output_rows = output_deriv.
NumRows();
782 for (
int32 s = 0; s < num_steps; s++) {
788 input_row_start, output_rows,
800 temp_num_cols != input.
NumCols()) {
811 temp_num_cols, temp_num_cols);
819 temp_mat_part.CopyFromMat(input_part.ColRange(step.
first_column,
823 temp_mat_part.Data(), temp_mat_part.NumRows() * cc.
height_out,
827 temp_mat_part_reshaped,
kNoTrans, 1.0);
830 input_part.Data(), input_part.NumRows() * cc.
height_out,
860 if (input_rows != required_input_rows) {
861 if (input_rows % required_input_rows != 0)
862 KALDI_ERR <<
"Input matrix has wrong size.";
866 multiple = input_rows / required_input_rows,
867 new_num_cols = num_cols * multiple,
868 new_stride = new_num_cols;
870 input.
Data(), required_input_rows, new_num_cols, new_stride);
891 t_start += num_time_steps_per_chunk) {
893 this_num_t_out = std::min<int32>(num_t_left,
894 num_time_steps_per_chunk),
895 this_num_t_in = this_num_t_out + num_extra_in;
908 alpha, &temp_part, params_deriv);
913 alpha, &temp_mat, params_deriv);
920 *model_padded = model;
922 int32 min_height_offset = model.
offsets[0].height_offset,
923 max_height_offset = model.
offsets[0].height_offset,
924 num_offsets = model.
offsets.size();
925 for (
int32 i = 1;
i < num_offsets;
i++) {
926 min_height_offset = std::min<int32>(min_height_offset,
928 max_height_offset = std::max<int32>(max_height_offset,
932 max_required_input = max_height_offset + max_output_height,
933 min_required_input = min_height_offset + 0;
934 int32 bottom_padding = -min_required_input,
935 top_padding = max_required_input - (model.
height_in - 1);
936 if (bottom_padding < 0)
940 model_padded->
height_in += bottom_padding + top_padding;
941 for (
int32 i = 0;
i < num_offsets;
i++)
942 model_padded->
offsets[
i].height_offset += bottom_padding;
958 int32 temp_rows = 0, temp_cols = 0;
959 for (
size_t i = 0;
i < computation->
steps.size();
i++) {
963 bool columns_are_contiguous =
965 bool need_temp_matrix =
true;
966 if (columns_are_contiguous && step.
height_map[0] == 0 &&
970 need_temp_matrix =
false;
972 if (need_temp_matrix && this_num_cols > temp_cols)
973 temp_cols = this_num_cols;
979 BaseFloat num_megabytes = (4 * (temp_rows / 1000.0) * (temp_cols / 1000.0)),
982 int32 ratio = 1.0 + num_megabytes / megabyte_limit;
987 int32 new_num_t_out = (computation->
num_t_out + ratio - 1) / ratio;
988 temp_rows = new_num_t_out * computation->
num_images;
989 BaseFloat new_num_megabytes = (4 * (temp_rows / 1000.0) * (temp_cols / 1000.0));
991 if (new_num_megabytes > 1.01 * megabyte_limit) {
992 KALDI_WARN <<
"Memory consumed in convolution is more than requested " 993 <<
"(maybe very long time sequence?)";
1006 int32 bottom_padding = (model_padded.
offsets[0].height_offset -
1007 model.
offsets[0].height_offset),
1009 top_padding = total_padding - bottom_padding;
1022 unpadded_input_height = model.
height_in,
1023 padded_input_height = model_padded.
height_in,
1024 ratio = old_computation_height_in / padded_input_height;
1026 computation->
height_in = ratio * unpadded_input_height;
1027 for (
int32 s = 0; s < num_steps; s++) {
1030 for (
int32 i = 0;
i < height_map_size;
i++) {
1035 int32 h = c % padded_input_height,
1036 m = c / padded_input_height;
1038 if (h < bottom_padding || h >= padded_input_height - top_padding) {
1041 step.
height_map[
i] = (h - bottom_padding) + m * unpadded_input_height;
1047 computation->
Check();
1079 if (first_desired_input_t < io->start_t_in) {
1086 int32 last_desired_input_t =
1093 if (last_desired_input_t > last_input_t) {
1113 std::vector<ConvolutionModel::Offset>::iterator
1114 iter = model->
offsets.begin(),
1116 for (; iter != end; ++iter)
1117 iter->time_offset += shift;
1119 std::set<int32> temp;
1120 std::set<int32>::const_iterator iter;
1123 temp.insert(*iter + shift);
1128 temp.insert(*iter + shift);
1199 io_appended->num_t_in /= ratio;
1211 *model_appended = model;
1222 KALDI_ASSERT(orig_time_step_in * ratio == time_step_out);
1241 model_appended->
offsets.resize(num_offsets);
1243 for (
int32 i = 0;
i < num_offsets;
i++) {
1251 orig_time_step_in == 0);
1255 row_offset * old_height;
1276 int32 largest_required_temp_cols = 0;
1277 for (std::vector<ConvolutionStep>::iterator iter = steps.begin();
1278 iter != steps.end(); ++iter) {
1280 std::vector<int32> columns;
1282 columns.resize(temp_height * num_filters_in);
1283 for (
int32 h = 0; h < temp_height; h++) {
1287 columns[h * num_filters_in + f] = step.
height_map[h] * num_filters_in + f;
1290 columns[h * num_filters_in + f] = -1;
1294 std::vector<std::vector<int32> > backward_columns;
1297 for (
size_t i = 0;
i < backward_columns.size();
i++)
1307 bool need_temp_matrix =
1310 if (need_temp_matrix) {
1311 largest_required_temp_cols = std::max<int32>(
1312 largest_required_temp_cols,
static_cast<int32>(columns.size()));
1331 bool allow_extra_input) {
1335 if (!allow_extra_input) {
1344 std::set<int32> input_times_to_check;
1348 for (std::set<int32>::const_iterator iter =
1352 int32 offset = *iter;
1353 input_times_to_check.insert(t_out + offset);
1356 for (std::set<int32>::const_iterator iter = input_times_to_check.begin();
1357 iter != input_times_to_check.end(); ++iter) {
1360 KALDI_ERR <<
"Error checking model and IO: time " << t
1361 <<
" is required but not in the input.";
1369 const std::vector<Index> &input_indexes,
1370 const std::vector<Index> &output_indexes,
1373 std::vector<Index> *input_indexes_modified,
1374 std::vector<Index> *output_indexes_modified) {
1399 &model_appended, &io_appended);
1413 input_indexes_modified, output_indexes_modified);
1421 size_t size = vec.size();
1423 for (
size_t i = 0;
i + 1 < size;
i++) {
1424 int32 diff = vec[
i+1] - vec[
i];
1426 ans =
Gcd(ans, diff);
1434 int32 *num_values) {
1436 *start = t_values[0];
1442 int32 last_value = t_values.back();
1443 *num_values = 1 + (last_value - *start) / *step;
1470 static void CreateIndexes(
const std::vector<std::pair<int32, int32> > &n_x_pairs,
1472 int32 reorder_t, std::vector<Index> *indexes) {
1473 KALDI_ASSERT(reorder_t >= 1 && num_t_values % reorder_t == 0 && t_step >= 0);
1478 int32 num_n_x_pairs = n_x_pairs.size();
1480 indexes->reserve(num_n_x_pairs * num_t_values);
1481 int32 outer_t_step = t_step * reorder_t,
1482 t_end = t_start + (num_t_values * t_step);
1484 for (
int32 t_block = t_start; t_block < t_end; t_block += outer_t_step) {
1485 for (
int32 nx = 0; nx < num_n_x_pairs; nx++) {
1486 index.
n = n_x_pairs[nx].first;
1487 index.x = n_x_pairs[nx].second;
1488 for (
int32 t = t_block; t < t_block + outer_t_step; t += t_step) {
1490 indexes->push_back(index);
1495 KALDI_ASSERT(indexes->size() == num_n_x_pairs * num_t_values);
1506 std::vector<Index> *indexes) {
1507 std::unordered_set<Index, IndexHasher> ref_set;
1508 for (std::vector<Index>::const_iterator iter = ref_indexes.begin();
1509 iter != ref_indexes.end(); ++iter)
1510 ref_set.insert(*iter);
1512 for (std::vector<Index>::iterator iter = indexes->begin();
1513 iter != indexes->end(); ++iter) {
1514 if (ref_set.count(*iter) == 0)
1520 const std::vector<Index> &input_indexes,
1521 const std::vector<Index> &output_indexes,
1523 std::vector<std::pair<int32, int32> > n_x_pairs;
1528 std::vector<std::pair<int32, int32> > n_x_pairs_2;
1529 GetNxList(output_indexes, &n_x_pairs_2);
1532 std::vector<int32> t_values;
1533 GetTList(input_indexes, &t_values);
1536 GetTList(output_indexes, &t_values);
1545 const std::vector<Index> &orig_input_indexes,
1546 const std::vector<Index> &orig_output_indexes,
1547 std::vector<Index> *input_indexes,
1548 std::vector<Index> *output_indexes) {
1549 std::unordered_set<Index, IndexHasher> input_set, output_set;
1550 for (std::vector<Index>::const_iterator iter = orig_input_indexes.begin();
1551 iter != orig_input_indexes.end(); ++iter)
1552 input_set.insert(*iter);
1553 for (std::vector<Index>::const_iterator iter = orig_output_indexes.begin();
1554 iter != orig_output_indexes.end(); ++iter)
1555 output_set.insert(*iter);
1556 std::vector<std::pair<int32, int32> > n_x_pairs;
1557 GetNxList(orig_input_indexes, &n_x_pairs);
1593 computation->
steps.clear();
1596 cur_start_offset = 0, cur_end_offset = 0;
1597 for(; cur_start_offset < num_offsets; cur_start_offset = cur_end_offset) {
1598 cur_end_offset = cur_start_offset;
1599 while (cur_end_offset < num_offsets &&
1600 model.
offsets[cur_end_offset].time_offset ==
1601 model.
offsets[cur_start_offset].time_offset)
1605 int32 this_num_offsets = cur_end_offset - cur_start_offset;
1606 int32 time_offset = model.
offsets[cur_start_offset].time_offset;
1615 modified_time_offset % t_step == 0);
1621 for (
int32 h_out = 0;
1624 for (
int32 o = cur_start_offset; o < cur_end_offset; o++) {
1625 int32 this_height_offset = model.
offsets[o].height_offset,
1626 h_in = h_out + this_height_offset;
1636 computation->
steps.push_back(step);
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
MatrixIndexT Stride() const
int32 height_subsample_out
std::vector< CuArray< int32 > > backward_columns
void GetTList(const std::vector< Index > &indexes, std::vector< int32 > *t_values)
This function outputs a sorted, unique list of the 't' values that are encountered in the provided li...
void Write(std::ostream &os, bool binary) const
static bool VectorIsContiguous(const std::vector< int32 > &vec)
static int32 DivideRoundingDown(int32 a, int32 b)
Returns a / b, rounding towards negative infinity in all cases.
void ConvolveBackwardParams(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > &output_deriv, BaseFloat alpha, CuMatrixBase< BaseFloat > *params_deriv)
This does the part of the backward derivative computation of convolution, that computes derivatives w...
void WriteIntegerPairVector(std::ostream &os, bool binary, const std::vector< std::pair< T, T > > &v)
Function for writing STL vectors of pairs of integer types.
void CopyFromVec(const std::vector< T > &src)
This function resizes if needed.
void CopyToVec(std::vector< T > *dst) const
This function resizes *dst if needed.
static int32 RoundDownToMultipleOf(int32 i, int32 n)
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
bool Check(bool check_heights_used=true, bool allow_height_padding=true) const
static void ConvolveBackwardParamsInternal(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > &output_deriv, BaseFloat alpha, CuMatrixBase< BaseFloat > *temp_mat, CuMatrixBase< BaseFloat > *params_deriv)
void Read(std::istream &is, bool binary)
static void ConvolveBackwardDataInternal(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > ¶ms, const CuMatrixBase< BaseFloat > &output_deriv, CuMatrixBase< BaseFloat > *temp_mat, CuMatrixBase< BaseFloat > *input_deriv)
int32 GetVerboseLevel()
Get verbosity level, usually set via command line '–verbose=' switch.
static void RegularizeTList(std::vector< int32 > &t_values, int32 *start, int32 *step, int32 *num_values)
static int32 FindGcdOfDifferences(std::vector< int32 > &vec)
This comment explains the basic framework used for everything related to time-height convolution...
static void CreateIndexes(const std::vector< std::pair< int32, int32 > > &n_x_pairs, int32 t_start, int32 t_step, int32 num_t_values, int32 reorder_t, std::vector< Index > *indexes)
Creates a vector of indexes with a regular structure, according to these specifications.
This class represents a matrix that's stored on the GPU if we have one, and in memory if not...
bool columns_are_contiguous
void ReadIntegerPairVector(std::istream &is, bool binary, std::vector< std::pair< T, T > > *v)
Function for reading STL vector of pairs of integer types.
struct Index is intended to represent the various indexes by which we number the rows of the matrices...
std::set< int32 > all_time_offsets
static void ConvolveForwardInternal(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > ¶ms, CuMatrixBase< BaseFloat > *temp_mat, CuMatrixBase< BaseFloat > *output)
void ExpectOneOrTwoTokens(std::istream &is, bool binary, const std::string &token1, const std::string &token2)
This function is like ExpectToken but for two tokens, and it will either accept token1 and then token...
std::vector< int32 > height_map
void GetIndexesForComputation(const ConvolutionComputationIo &io, const std::vector< Index > &orig_input_indexes, const std::vector< Index > &orig_output_indexes, std::vector< Index > *input_indexes, std::vector< Index > *output_indexes)
This function computes the reordered and possibly padded indexes corresponding to the computation in ...
This file contains some fairly low-level utilities for implementing convolutional neural networks and...
void UnPadModelHeight(const ConvolutionComputationOptions &opts, const ConvolutionModel &model, const ConvolutionModel &model_padded, ConvolutionComputation *computation)
This function modifies, if necessary, a computation that has been built for the model 'model_padded'...
void ReadIntegerVector(std::istream &is, bool binary, std::vector< T > *v)
Function for reading STL vector of integer types.
std::vector< ConvolutionStep > steps
static void ExpectToken(const std::string &token, const std::string &what_we_are_parsing, const std::string **next_token)
void ConvolveBackwardData(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > ¶ms, const CuMatrixBase< BaseFloat > &output_deriv, CuMatrixBase< BaseFloat > *input_deriv)
This does the part of the backward derivative computation of convolution, that propagates derivatives...
void MakeComputation(const ConvolutionModel &model, ConvolutionComputationIo &io, const ConvolutionComputationOptions &opts, ConvolutionComputation *computation)
void Read(std::istream &is, bool binary)
static int32 PrepareIoForAppending(ConvolutionComputationIo *io, ConvolutionComputationIo *io_appended)
void AppendInputFrames(const ConvolutionModel &model, ConvolutionComputationIo *io, ConvolutionModel *model_appended, ConvolutionComputationIo *io_appended)
This function takes an input model and I/O specification, and it modifies both of them if necessary t...
void AddMatMat(Real alpha, const CuMatrixBase< Real > &A, MatrixTransposeType transA, const CuMatrixBase< Real > &B, MatrixTransposeType transB, Real beta)
C = alpha * A(^T)*B(^T) + beta * C.
void CompileConvolutionComputation(const ConvolutionModel &model, const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, const ConvolutionComputationOptions &opts, ConvolutionComputation *computation, std::vector< Index > *input_indexes_modified, std::vector< Index > *output_indexes_modified)
This function does the compilation for a convolution computation; it's a wrapper for the functions be...
This class is used for a piece of a CuMatrix.
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
std::vector< Offset > offsets
void PadModelHeight(const ConvolutionModel &model, ConvolutionModel *model_padded)
This function takes a model that might require zero padding in the height dimension and outputs a mod...
const Real * Data() const
Return data pointer (const).
static void ShiftAllTimeOffsets(int32 shift, ConvolutionModel *model)
static void ReverseColumnMapping(const std::vector< int32 > &columns, int32 input_dim, std::vector< std::vector< int32 > > *backward_columns)
This function, used in ConvolutionComputation::ComputeDerived(), reverses a mapping that may not be u...
This struct represents the structure of a convolution computation.
Matrix for CUDA computing.
MatrixIndexT NumCols() const
void GetComputationIo(const std::vector< Index > &input_indexes, const std::vector< Index > &output_indexes, ConvolutionComputationIo *io)
This function takes lists of input and output indexes to a computation (e.g.
bool operator==(const ConvolutionModel &other) const
#define KALDI_ASSERT(cond)
void Read(std::istream &is, bool binary)
This struct contains options for compiling the convolutional computation.
std::set< int32 > required_time_offsets
void WriteIntegerVector(std::ostream &os, bool binary, const std::vector< T > &v)
Function for writing STL vectors of integer types.
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
void CopyCols(const CuMatrixBase< Real > &src, const CuArrayBase< MatrixIndexT > &indexes)
Copies column r from column indexes[r] of src.
void Write(std::ostream &os, bool binary) const
void Write(std::ostream &os, bool binary) const
static void ComputeTempMatrixSize(const ConvolutionComputationOptions &opts, ConvolutionComputation *computation)
This function sets 'temp_rows' and 'temp_cols' in 'computation'.
static void SetSomeIndexesBlank(const std::vector< Index > &ref_indexes, std::vector< Index > *indexes)
This function modifies 'indexes' by, for any Indexes which was not present in 'ref_indexes', setting the 't' value to kNoTime.
MatrixIndexT NumRows() const
Dimensions.
MatrixIndexT Dim() const
Return the vector dimension.
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
int32 time_offsets_modulus
void ConvolveForward(const ConvolutionComputation &cc, const CuMatrixBase< BaseFloat > &input, const CuMatrixBase< BaseFloat > ¶ms, CuMatrixBase< BaseFloat > *output)
This does the forward computation of convolution.
void CheckModelAndIo(const ConvolutionModel &model, const ConvolutionComputationIo &io, bool allow_extra_input)
Check that this model and this I/O request are compatible in terms of required context, etc, and crash if not.
static bool TimeValueInInput(const ConvolutionComputationIo &io, int32 t)
void PadComputationInputTime(const ConvolutionModel &model, ConvolutionComputationIo *io)
This function extends the set of input indexes that the computation has, to account for any required ...
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
void GetNxList(const std::vector< Index > &indexes, std::vector< std::pair< int32, int32 > > *pairs)
This function outputs a unique, lexicographically sorted list of the pairs of (n, x) values that are ...