1. Return a TfLiteApplicationError instead of TfLiteError when trying to apply a delegate that doesn't allow dynamic tensors on a graph with dynamic tensors.

2. Add comments on error statuses defined in TfLiteStatus.

PiperOrigin-RevId: 337802774
Change-Id: Ieb828b04b9cb46c692210cd2786fed77adb80ecc
This commit is contained in:
Chao Mei 2020-10-19 00:30:15 -07:00 committed by TensorFlower Gardener
parent 861f63a327
commit 6f440e215d
6 changed files with 90 additions and 3 deletions
tensorflow/lite

View File

@ -46,8 +46,17 @@ extern "C" {
typedef enum TfLiteStatus {
kTfLiteOk = 0,
// Generally referring to an error in the runtime (i.e. interpreter)
kTfLiteError = 1,
// Generally referring to an error from a TfLiteDelegate itself.
kTfLiteDelegateError = 2,
// Generally referring to an error in applying a delegate due to
// incompatibility between runtime and delegate, e.g., this error is returned
// when trying to apply a TfLite delegate onto a model graph that's already
// immutable.
kTfLiteApplicationError = 3
} TfLiteStatus;

View File

@ -1526,7 +1526,7 @@ TfLiteStatus Subgraph::ModifyGraphWithDelegate(TfLiteDelegate* delegate) {
ReportError(
"Attempting to use a delegate that only supports static-sized "
"tensors with a graph that has dynamic-sized tensors.");
return kTfLiteError;
return kTfLiteApplicationError;
}
}

View File

@ -567,7 +567,8 @@ class Subgraph {
// delegate*. The Subgraph has been restored to its pre-delegation state.
// NOTE: This reverts all delegates previously applied to the Subgraph.
// 3. kTfLiteApplicationError : Delegation failed to be applied due to the
// state that the TfLite runtime is in. However, the Subgraph is still in a
// incompatibility with the TfLite runtime, e.g., the model graph is already
// immutable when applying the delegate. However, the Subgraph is still in a
// invokable state.
// 4. kTfLiteError: Unexpected/runtime failure.
TfLiteStatus ModifyGraphWithDelegate(TfLiteDelegate* delegate);

View File

@ -412,7 +412,11 @@ class Interpreter {
/// 2. kTfLiteDelegateError: Delegation failed due to an error in the
/// delegate. The Interpreter has been restored to its pre-delegation state.
/// NOTE: This undoes all delegates previously applied to the Interpreter.
/// 3. kTfLiteError: Unexpected/runtime failure.
/// 3. kTfLiteApplicationError : Delegation failed to be applied due to the
/// incompatibility with the TfLite runtime, e.g., the model graph is already
/// immutable when applying the delegate. However, the interpreter could still
/// be invoked.
/// 4. kTfLiteError: Unexpected/runtime failure.
/// WARNING: This is an experimental API and subject to change.
TfLiteStatus ModifyGraphWithDelegate(TfLiteDelegate* delegate);

View File

@ -49,6 +49,13 @@ class InterpreterTest : public ::testing::Test {
protected:
TfLiteContext* GetInterpreterContext() { return interpreter_.context_; }
std::vector<Interpreter::TfLiteDelegatePtr>*
mutable_lazy_delegate_providers() {
return &interpreter_.lazy_delegate_providers_;
}
bool HasDelegates() { return interpreter_.HasDelegates(); }
Interpreter interpreter_;
};
@ -1782,6 +1789,63 @@ TEST_F(TestCustomAllocation, ResizeTensorsWithEnoughMemory) {
VerifyInvoke();
}
// Tests related to lazy delegate providers that are primarily used for applying
// TfLite delegates by default.
class TestLazyDelegateProvider : public InterpreterTest {
protected:
struct DummyLazyDelegateProvider : public TfLiteDelegate {
explicit DummyLazyDelegateProvider(int64_t support_flags) {
data_ = static_cast<void*>(this);
flags = support_flags;
Prepare = [](TfLiteContext*, TfLiteDelegate* delegate) -> TfLiteStatus {
return kTfLiteOk;
};
}
};
void InitWithLazyDelegate(int64_t delegate_flags,
bool create_dyanmic_tensor = false) {
TfLiteRegistration reg = {nullptr, nullptr, nullptr, nullptr};
ASSERT_EQ(interpreter_.AddTensors(2), kTfLiteOk);
interpreter_.SetInputs({0});
interpreter_.SetOutputs({1});
interpreter_.AddNodeWithParameters({0}, {1}, nullptr, 0, nullptr, &reg);
Interpreter::TfLiteDelegatePtr delegate(
new DummyLazyDelegateProvider(delegate_flags),
[](TfLiteDelegate* delegate) {
auto* dummy =
static_cast<DummyLazyDelegateProvider*>(delegate->data_);
delete dummy;
});
mutable_lazy_delegate_providers()->push_back(std::move(delegate));
if (create_dyanmic_tensor) {
// Mark the output as dynamic tensor.
interpreter_.tensor(1)->data.raw = nullptr;
interpreter_.tensor(1)->allocation_type = kTfLiteDynamic;
}
}
};
TEST_F(TestLazyDelegateProvider, ApplicationSuccess) {
InitWithLazyDelegate(kTfLiteDelegateFlagsNone);
EXPECT_EQ(kTfLiteOk, interpreter_.AllocateTensors());
// We clear Interpreter::lazy_delegate_providers_ after they are tried out.
EXPECT_TRUE(mutable_lazy_delegate_providers()->empty());
EXPECT_TRUE(HasDelegates());
}
TEST_F(TestLazyDelegateProvider, ApplicationSkipped) {
InitWithLazyDelegate(kTfLiteDelegateFlagsNone,
true /* create_dyanmic_tensor */);
EXPECT_EQ(kTfLiteOk, interpreter_.AllocateTensors());
EXPECT_TRUE(mutable_lazy_delegate_providers()->empty());
// As the delegate doesn't allow dynamic tensor, the delegate won't be applied
// and the interpreter doesn't have any delegate applied.
EXPECT_FALSE(HasDelegates());
}
} // namespace
} // namespace tflite

View File

@ -46,8 +46,17 @@ extern "C" {
typedef enum TfLiteStatus {
kTfLiteOk = 0,
// Generally referring to an error in the runtime (i.e. interpreter)
kTfLiteError = 1,
// Generally referring to an error from a TfLiteDelegate itself.
kTfLiteDelegateError = 2,
// Generally referring to an error in applying a delegate due to
// incompatibility between runtime and delegate, e.g., this error is returned
// when trying to apply a TfLite delegate onto a model graph that's already
// immutable.
kTfLiteApplicationError = 3
} TfLiteStatus;