1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/delegates/interpreter_utils.h"
17
18 #include <string.h>
19
20 #include <memory>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24 #include "tensorflow/lite/delegates/delegate_test_util.h"
25 #include "tensorflow/lite/interpreter.h"
26 #include "tensorflow/lite/kernels/internal/compatibility.h"
27 #include "tensorflow/lite/testing/util.h"
28
29 namespace tflite {
30 namespace delegates {
31
32 using test_utils::SimpleDelegate;
33 using test_utils::TestDelegate;
34 using test_utils::TestFP16Delegation;
35
36 namespace {
37
TEST_F(TestDelegate,DelegateNodeInvokeFailureFallback)38 TEST_F(TestDelegate, DelegateNodeInvokeFailureFallback) {
39 delegate_ = std::unique_ptr<SimpleDelegate>(new SimpleDelegate(
40 {0, 1, 2}, kTfLiteDelegateFlagsNone, false /**fail_node_prepare**/,
41 0 /**min_ops_per_subset**/, true /**fail_node_invoke**/));
42 ASSERT_EQ(
43 interpreter_->ModifyGraphWithDelegate(delegate_->get_tf_lite_delegate()),
44 kTfLiteOk);
45 // Delegation modified execution plan.
46 ASSERT_EQ(interpreter_->execution_plan().size(), 1);
47
48 std::vector<float> input = {1.0f, 2.0f, 3.0f};
49 std::vector<float> expected_output = {2.0f, 4.0f, 6.0f};
50 constexpr int kOutputTensorIndex = 3;
51
52 memcpy(interpreter_->typed_tensor<float>(0), input.data(), 3 * sizeof(float));
53 memcpy(interpreter_->typed_tensor<float>(1), input.data(), 3 * sizeof(float));
54 EXPECT_EQ(
55 delegates::InterpreterUtils::InvokeWithCPUFallback(interpreter_.get()),
56 kTfLiteDelegateError);
57 // Delegation removed, returning to original execution plan.
58 ASSERT_EQ(interpreter_->execution_plan().size(), 3);
59 // Check outputs.
60 TfLiteTensor* tensor = interpreter_->tensor(kOutputTensorIndex);
61 for (int i = 0; i < 3; ++i) {
62 EXPECT_EQ(tensor->data.f[i], expected_output[i]) << i;
63 }
64 }
65
TEST_F(TestDelegate,TestFallbackWithMultipleDelegates)66 TEST_F(TestDelegate, TestFallbackWithMultipleDelegates) {
67 // First delegate only supports node 0.
68 // This delegate should support dynamic tensors, otherwise the second won't be
69 // applied.
70 delegate_ = std::unique_ptr<SimpleDelegate>(
71 new SimpleDelegate({0}, kTfLiteDelegateFlagsAllowDynamicTensors));
72 // Second delegate supports nodes 1 & 2, and makes the graph immutable.
73 delegate2_ = std::unique_ptr<SimpleDelegate>(new SimpleDelegate(
74 {1, 2}, kTfLiteDelegateFlagsNone, false /**fail_node_prepare**/,
75 0 /**min_ops_per_subset**/, true /**fail_node_invoke**/));
76 // Pre-delegation execution plan should have three nodes.
77 ASSERT_EQ(interpreter_->execution_plan().size(), 3);
78 ASSERT_EQ(
79 interpreter_->ModifyGraphWithDelegate(delegate_->get_tf_lite_delegate()),
80 kTfLiteOk);
81 ASSERT_EQ(
82 interpreter_->ModifyGraphWithDelegate(delegate2_->get_tf_lite_delegate()),
83 kTfLiteOk);
84 // Should be two delegates nodes.
85 ASSERT_EQ(interpreter_->execution_plan().size(), 2);
86
87 std::vector<float> input = {1.0f, 2.0f, 3.0f};
88 std::vector<float> expected_output = {2.0f, 4.0f, 6.0f};
89 constexpr int kOutputTensorIndex = 2;
90 TfLiteTensor* tensor = interpreter_->tensor(kOutputTensorIndex);
91
92 memcpy(interpreter_->typed_tensor<float>(0), input.data(), 3 * sizeof(float));
93 memcpy(interpreter_->typed_tensor<float>(1), input.data(), 3 * sizeof(float));
94 EXPECT_EQ(
95 delegates::InterpreterUtils::InvokeWithCPUFallback(interpreter_.get()),
96 kTfLiteDelegateError);
97 // All delegates should be undone.
98 EXPECT_EQ(interpreter_->execution_plan().size(), 3);
99 for (int i = 0; i < 3; ++i) {
100 EXPECT_EQ(tensor->data.f[i], expected_output[i]) << i;
101 }
102 }
103
TEST_P(TestFP16Delegation,DelegateInvokeWithCPUFallback)104 TEST_P(TestFP16Delegation, DelegateInvokeWithCPUFallback) {
105 delegate_ = std::make_unique<FP16Delegate>(
106 /**num_delegated_subsets**/ GetParam(), /**fail_node_prepare**/ false,
107 /**fail_node_invoke**/ true);
108 ASSERT_EQ(
109 interpreter_->ModifyGraphWithDelegate(delegate_->get_tf_lite_delegate()),
110 kTfLiteOk);
111
112 std::vector<float> input = {3.0f};
113 std::vector<float> expected_output = {16.0f};
114
115 const int input_tensor_idx = interpreter_->inputs()[0];
116 const int output_tensor_idx = interpreter_->outputs()[0];
117
118 memcpy(interpreter_->typed_tensor<float>(input_tensor_idx), input.data(),
119 sizeof(float));
120 EXPECT_EQ(
121 delegates::InterpreterUtils::InvokeWithCPUFallback(interpreter_.get()),
122 kTfLiteDelegateError);
123 TfLiteTensor* output_tensor = interpreter_->tensor(output_tensor_idx);
124 for (int i = 0; i < 1; ++i) {
125 EXPECT_EQ(output_tensor->data.f[i], expected_output[i]) << i;
126 }
127
128 ASSERT_EQ(interpreter_->execution_plan().size(), 8);
129 VerifyInvoke();
130 }
131
132 INSTANTIATE_TEST_SUITE_P(TestFP16Delegation, TestFP16Delegation,
133 ::testing::Values(1, 2));
134
135 } // anonymous namespace
136 } // namespace delegates
137 } // namespace tflite
138