Automated sync from github.com/tensorflow/tensorflow (#2395)
BUG=automated sync from upstream
NO_CHECK_TFLITE_FILES=automated sync from upstream
diff --git a/tensorflow/lite/core/c/common.cc b/tensorflow/lite/core/c/common.cc
index 5430fe2..fd7c415 100644
--- a/tensorflow/lite/core/c/common.cc
+++ b/tensorflow/lite/core/c/common.cc
@@ -384,44 +384,6 @@
TfLiteDelegate TfLiteDelegateCreate() { return TfLiteDelegate{}; }
-// LINT.IfChange
-#ifndef TF_LITE_STATIC_MEMORY
-TfLiteOpaqueDelegate* TfLiteOpaqueDelegateCreate(
- const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder) {
- if (!opaque_delegate_builder) return nullptr;
-
- TfLiteDelegate* result = new TfLiteDelegate{};
- result->opaque_delegate_builder = new TfLiteOpaqueDelegateBuilder{};
- *(result->opaque_delegate_builder) = *opaque_delegate_builder;
-
- return reinterpret_cast<TfLiteOpaqueDelegate*>(result);
-}
-
-void TfLiteOpaqueDelegateDelete(TfLiteOpaqueDelegate* opaque_delegate) {
- if (!opaque_delegate) return;
-
- const TfLiteDelegate* tflite_delegate =
- reinterpret_cast<const TfLiteDelegate*>(opaque_delegate);
- delete tflite_delegate->opaque_delegate_builder;
- delete tflite_delegate;
-}
-#endif // TF_LITE_STATIC_MEMORY
-
-void* TfLiteOpaqueDelegateGetData(const TfLiteOpaqueDelegate* delegate) {
- if (!delegate) return nullptr;
-
- // The following cast is safe only because this code is part of the
- // TF Lite runtime implementation. Apps using TF Lite should not rely on
- // 'TfLiteOpaqueDelegate' and 'TfLiteDelegate' being equivalent.
- const auto* tflite_delegate =
- reinterpret_cast<const TfLiteDelegate*>(delegate);
-
- if (!tflite_delegate->opaque_delegate_builder) return tflite_delegate->data_;
-
- return tflite_delegate->opaque_delegate_builder->data;
-}
-// LINT.ThenChange(Google-internal path)
-
// Returns a tensor data allocation strategy.
TfLiteAllocationStrategy TfLiteTensorGetAllocationStrategy(
const TfLiteTensor* const t) {
diff --git a/tensorflow/lite/core/c/common.h b/tensorflow/lite/core/c/common.h
index b2ceecb..4e48901 100644
--- a/tensorflow/lite/core/c/common.h
+++ b/tensorflow/lite/core/c/common.h
@@ -1348,15 +1348,19 @@
TfLiteDelegate TfLiteDelegateCreate(void);
/// `TfLiteOpaqueDelegateBuilder` is used for constructing
-/// `TfLiteOpaqueDelegate`, see `TfLiteOpaqueDelegateCreate` below. Note:
-/// This struct is not ABI stable.
+/// `TfLiteOpaqueDelegate`, see `TfLiteOpaqueDelegateCreate` in c_api_opaque.h.
+/// NOTE: This struct is not ABI stable.
///
/// For forward source compatibility `TfLiteOpaqueDelegateBuilder` objects
/// should be brace-initialized, so that all fields (including any that might be
/// added in the future) get zero-initialized. The purpose of each field is
/// exactly the same as with `TfLiteDelegate`.
///
-/// WARNING: This is an experimental interface that is subject to change.
+/// NOTE: This type is part of the TensorFlow Lite Extension APIs.
+/// We reserve the right to make changes to this API in future releases,
+/// potentially including non-backwards-compatible changes, on a different
+/// schedule than for the other TensorFlow Lite APIs. See
+/// https://www.tensorflow.org/guide/versions#separate_version_number_for_tensorflow_lite_extension_apis.
typedef struct TfLiteOpaqueDelegateBuilder {
/// Data that delegate needs to identify itself. This data is owned by the
/// delegate. The delegate is owned in the user code, so the delegate is
@@ -1393,41 +1397,23 @@
int64_t flags;
} TfLiteOpaqueDelegateBuilder;
-// LINT.IfChange
#ifndef TF_LITE_STATIC_MEMORY
-/// Creates an opaque delegate and returns its address. The opaque delegate
-/// will behave according to the provided `opaque_delegate_builder`. The
-/// lifetime of the objects pointed to by any of the fields within the
-/// `opaque_delegate_builder` must outlive the returned
-/// `TfLiteOpaqueDelegate` and any `TfLiteInterpreter`,
-/// `TfLiteInterpreterOptions`, `tflite::Interpreter`, or
-/// `tflite::InterpreterBuilder` that the delegate is added to. The returned
-/// address should be passed to `TfLiteOpaqueDelegateDelete` for deletion. If
-/// `opaque_delegate_builder` is a null pointer, then a null pointer will be
-/// returned.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
TfLiteOpaqueDelegate* TfLiteOpaqueDelegateCreate(
const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder);
-/// Deletes the provided opaque `delegate`. This function has no effect if the
-/// `delegate` is a null pointer.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
void TfLiteOpaqueDelegateDelete(TfLiteOpaqueDelegate* delegate);
#endif // TF_LITE_STATIC_MEMORY
-/// Returns a pointer to the data associated with the provided opaque
-/// `delegate`.
-///
-/// A null pointer will be returned when:
-/// - The `delegate` is null.
-/// - The `data` field of the `TfLiteOpaqueDelegateBuilder` used to construct
-/// the `delegate` was null.
-/// - Or in case of any other error.
-/// - The `delegate` has been constructed via a `TfLiteOpaqueDelegateBuilder`,
-/// but the `data` field of the `TfLiteOpaqueDelegateBuilder` is null.
-///
-/// The data_ field of `delegate` will be returned if the
-/// `opaque_delegate_builder` field is null.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
void* TfLiteOpaqueDelegateGetData(const TfLiteOpaqueDelegate* delegate);
-// LINT.ThenChange(Google-internal path)
/// Returns a tensor data allocation strategy.
TfLiteAllocationStrategy TfLiteTensorGetAllocationStrategy(
diff --git a/tensorflow/lite/kernels/internal/portable_tensor_utils.h b/tensorflow/lite/kernels/internal/portable_tensor_utils.h
index c28892c..03bfdc8 100644
--- a/tensorflow/lite/kernels/internal/portable_tensor_utils.h
+++ b/tensorflow/lite/kernels/internal/portable_tensor_utils.h
@@ -259,7 +259,7 @@
const int8_t* __restrict__ matrix, const uint8_t* __restrict__ ledger,
const int m_rows, const int m_cols, const int8_t* __restrict__ vectors,
const float* __restrict__ scaling_factors, int n_batch,
- float* __restrict__ result);
+ float* __restrict__ result, const float* per_channel_scale = nullptr);
// Same as the above 8, 8, 8 integer matmul except for the presence of zero
// point and non-accumulative.
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
index d386203..b519d81 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
@@ -294,7 +294,8 @@
void PortableSparseMatrixBatchVectorMultiplyAccumulate(
const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
const int m_cols, const int8_t* __restrict__ vectors,
- const float* scaling_factors, int n_batch, float* __restrict__ result) {
+ const float* scaling_factors, int n_batch, float* __restrict__ result,
+ const float* per_channel_scale) {
static const int kBlockSize = 16;
TFLITE_DCHECK_EQ( // NOLINT
m_cols % kBlockSize, 0);
@@ -319,7 +320,11 @@
dotprod += (*row_ptr++) * (*vector_block_ptr++);
} // for block
} // for num_nonzero_blocks
- result[batch * m_rows + row] += dotprod * batch_scaling_factor;
+ float scaling_factor = batch_scaling_factor;
+ if (per_channel_scale) {
+ scaling_factor *= per_channel_scale[row];
+ }
+ result[batch * m_rows + row] += dotprod * scaling_factor;
} // for row
} // for batch
}
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
index 0416db0..ab0185e 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
@@ -129,10 +129,11 @@
void SparseMatrixBatchVectorMultiplyAccumulate(
const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
const int m_cols, const int8_t* __restrict__ vectors,
- const float* scaling_factors, int n_batch, float* __restrict__ result) {
+ const float* scaling_factors, int n_batch, float* __restrict__ result,
+ const float* per_channel_scale) {
PortableSparseMatrixBatchVectorMultiplyAccumulate(
- matrix, ledger, m_rows, m_cols, vectors, scaling_factors, n_batch,
- result);
+ matrix, ledger, m_rows, m_cols, vectors, scaling_factors, n_batch, result,
+ per_channel_scale);
}
void MatrixBatchVectorMultiplyAccumulate(
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
index 6c404d5..6a1f18e 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
@@ -99,7 +99,8 @@
void PortableSparseMatrixBatchVectorMultiplyAccumulate(
const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
const int m_cols, const int8_t* __restrict__ vectors,
- const float* scaling_factors, int n_batch, float* __restrict__ result);
+ const float* scaling_factors, int n_batch, float* __restrict__ result,
+ const float* per_channel_scale);
// Dot product of two vectors.
float PortableVectorVectorDotProduct(const float* vector1, const float* vector2,