diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc index b953785478..9f4ff8aa26 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc @@ -808,6 +808,20 @@ void UniDirectionalGru::Compute(const gsl::span& inputs_arg, } } + // zero any values beyond the evaluated steps + if (output_sequence && max_sequence_length < seq_length_) { + if (output_step_length == batch_size_ * hidden_size_) { // contiguous + const auto span_to_zero = outputs.subspan( + max_sequence_length * output_step_length, (seq_length_ - max_sequence_length) * output_step_length); + std::fill_n(span_to_zero.begin(), span_to_zero.size(), T{}); + } else { + for (int i = max_sequence_length; i < seq_length_; ++i) { // non-contiguous + const auto span_to_zero = outputs.subspan(i * output_step_length, batch_size_ * hidden_size_); + std::fill_n(span_to_zero.begin(), span_to_zero.size(), T{}); + } + } + } + if (output_sequence && direction_ == kReverse) { ReverseSequence(outputs, original_outputs, sequence_lengths, seq_length_, diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc index c5d05f8e4f..d2876f161e 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc @@ -971,6 +971,20 @@ void UniDirectionalLstm::Compute(const gsl::span& inputs_arg, } } + // zero any values beyond the evaluated steps + if (output_sequence && max_sequence_length < seq_length_) { + if (output_step_length == batch_size_ * hidden_size_) { // contiguous + const auto span_to_zero = outputs.subspan( + max_sequence_length * output_step_length, (seq_length_ - max_sequence_length) * output_step_length); + std::fill_n(span_to_zero.begin(), span_to_zero.size(), T{}); + } else { + for (int i = max_sequence_length; i < seq_length_; ++i) { // non-contiguous + const auto span_to_zero = outputs.subspan(i * output_step_length, batch_size_ * hidden_size_); + std::fill_n(span_to_zero.begin(), span_to_zero.size(), T{}); + } + } + } + if (output_sequence && direction_ == Direction::kReverse) ReverseSequence(outputs, original_outputs, sequence_lengths, seq_length_, batch_size_, hidden_size_, num_directions); diff --git a/onnxruntime/test/providers/cpu/rnn/deep_cpu_gru_op_test.cc b/onnxruntime/test/providers/cpu/rnn/deep_cpu_gru_op_test.cc index e4143d529e..e0010423b1 100644 --- a/onnxruntime/test/providers/cpu/rnn/deep_cpu_gru_op_test.cc +++ b/onnxruntime/test/providers/cpu/rnn/deep_cpu_gru_op_test.cc @@ -241,7 +241,7 @@ void DefaultActivationsSimpleWeightsWithBias(std::string direction, RunGruTest(X_data, W_data, R_data, Y_data, {}, input_size, batch_size, hidden_size, seq_length, &B_data, nullptr, nullptr, direction, 999.f, /* output_sequence*/ true, linear_before_reset); -} // namespace test +} TEST(GRUTest, ForwardDefaultActivationsSimpleWeightsWithBiasBatchParallel) { std::vector Y_data{ @@ -336,7 +336,7 @@ class DeepCpuGruOpTestContext { std::vector gru_input_weights_; std::vector gru_recurrent_weights_; std::vector gru_bias_; -}; // namespace test +}; DeepCpuGruOpTestContext::DeepCpuGruOpTestContext(const std::string direction, const std::vector& activations, @@ -459,7 +459,7 @@ void DeepCpuGruOpTestContext::RunTest(const std::vector& X, const std::vector& expected_Y, const std::vector& expected_Y_h, const bool linear_before_reset) { - //run with and without output_sequence + //run with and without output_sequence ::onnxruntime::test::RunGruTest(X, gru_input_weights_, gru_recurrent_weights_, expected_Y, expected_Y_h, input_size_, batch_size, hidden_dim_, seq_length, @@ -469,7 +469,7 @@ void DeepCpuGruOpTestContext::RunTest(const std::vector& X, direction_, 9999999999.f, /*output_sequence*/ true, - linear_before_reset, + linear_before_reset, activation_func_names_, alphas_, betas_); @@ -819,6 +819,35 @@ TEST(GRUTest, ONNXRuntime_TestGRUOpSequenceLengthWithPartialZero) { ctx.RunTest(X, batch_size, seq_length, sequence_length, &initial_h, expected_Y, expected_Y_h); } +TEST(GRUTest, ONNXRuntime_TestGRUOpSequenceLengthShorterThanInputSequenceLength) { + const std::string direction = "bidirectional"; + const std::vector activations = {"sigmoid", "tanh", "sigmoid", "tanh"}; + + DeepCpuGruOpTestContext ctx(direction, activations); + + const int batch = 1; + const int seq_length = 2; + + std::vector X = {-0.455351f, -0.276391f, + -0.185934f, -0.269585f}; + + std::vector sequence_lengths = {1}; + + std::vector initial_h = {0.0f, 0.0f, + -0.04566499f, 0.04621252f}; + + std::vector expected_Y = {-0.03255286f, 0.0774838f, + -0.05469977f, 0.1004222f, + + 0.0f, 0.0f, + 0.0f, 0.0f}; + + std::vector expected_Y_h = {-0.03255286f, 0.0774838f, + -0.05469977f, 0.1004222f}; + + ctx.RunTest(X, batch, seq_length, sequence_lengths, &initial_h, expected_Y, expected_Y_h); +} + TEST(GRUTest, ONNXRuntime_TestGRUOpSequenceLengthAllZeros) { const std::string direction = "forward"; const std::vector activations = {"sigmoid", "tanh"}; diff --git a/onnxruntime/test/providers/cpu/rnn/deep_cpu_lstm_op_test.cc b/onnxruntime/test/providers/cpu/rnn/deep_cpu_lstm_op_test.cc index 62de9ab143..eaa0cc649f 100644 --- a/onnxruntime/test/providers/cpu/rnn/deep_cpu_lstm_op_test.cc +++ b/onnxruntime/test/providers/cpu/rnn/deep_cpu_lstm_op_test.cc @@ -1059,5 +1059,38 @@ TEST(LSTMTest, ONNXRuntime_TestLSTMSequenceLengthPartialZeros) { &sequence_length, use_bias, use_peepholes); } +// TODO this test fails for nGraph - need to investigate why +#ifndef USE_NGRAPH +TEST(LSTMTest, ONNXRuntime_TestLSTMSequenceLengthShorterThanInputSequenceLength) { + const int seq_len = 2; + const int batch_size = 1; + + std::vector X_data = {-0.455351f, -0.276391f, + -0.185934f, -0.269585f}; + + std::vector sequence_length = {1}; + + std::vector initial_h = {0.0f, 0.0f, + -0.0306872f, 0.028035f}; + + std::vector initial_c = {0.0f, 0.0f, + -0.07243599f, 0.0467052f}; + + std::vector Y_data = {-0.0251062f, 0.0561262f, + -0.0318928f, 0.0762679f, + + 0.0f, 0.0f, + 0.0f, 0.0f}; + + std::vector Y_h_data = {-0.0251062f, 0.0561262f, + -0.0318928f, 0.0762679f}; + + std::string direction = "bidirectional"; + + LstmOpContext2x1x2x2 context(direction); + context.RunTest(X_data, batch_size, seq_len, &initial_h, &initial_c, Y_data, Y_h_data, {}, &sequence_length); +} +#endif // USE_NGRAPH + } // namespace test } // namespace onnxruntime